sinclairzx81/typebox

no schema with key or ref

Closed this issue · 3 comments

So I am experiencing problems with Type.Union - I have tried to make it as digestable as possible in this repo:
https://github.com/Jesbjerg/fastify-example

To serve:
npm i
npm run start

Error on response: "statusCode": 500,
"error": "Internal Server Error",
"message": "no schema with key or ref "urn:test:test:test:test:test#response#/properties/test/anyOf/0""

I have seen some issues addressing this on Fastify - but even with their fixes, this issue is not resolved.
Specifically referring to:
fastify/fastify#4108

Deps:
"@sinclair/typebox": "^0.24.20",
"fastify": "^4.3.0"

@Jesbjerg Hi. Had a look at the schema, and structurally it's ok, however the $id string looks unusual. I'm not sure you want to be specifying #response in the $id as hashes are typically reserved for $ref to reference a relative json pointer path (some property relative to the current schema, or foo#property if referencing external schema with $id: 'foo').

You can find a little bit more information on $id and $ref at the following location https://json-schema.org/understanding-json-schema/structuring.html

Error

The actual error you see is coming from fast-json-stringify. Below is a minimal reproduction that triggers the error, but note that the commented line (which omits the #response) works ok.

const fastJson = require('fast-json-stringify')
import { Type } from '@sinclair/typebox'

export const Response = Type.Object({
    test: Type.Union([Type.Boolean(), Type.String()])
}, {
    $id: "urn:test:test:test:test:test#response", // fails
    // $id: "urn:test:test:test:test:test",       // ok
    description: "Schema for test",
    additionalProperties: false
})

const stringify = fastJson(Response)

console.log(stringify({ test: true })) // Error: no schema with key or ref "urn:test:test:test:test:test#response#/properties/test/anyOf/0"

If you feel this is an error, it would be best to submit the above code as an issue on the fast-json-stringify project (as TypeBox is two projects removed from that project). I do note that Ajv does accept the #response on the $id, so it might be good letting the fast-json-stringify maintainers know (as I assume if Ajv accepts $id of that form, then fast-json-stringify should too). But to get things working, just omitting the #response on the id might be the way to go.

Will keep this issue open for a day or so in case you have any questions.
Hope this helps!
S

Thank you for the very elaborate answer. It helped me understand the problem more clearly. I will definitely check with fast-json-stringify, because my project is using hashtags like this everywhere in the codebase without any inherent problem associated - until now that is... Would you have any idea of why the combination of union types and hashtags could be a problem?

Would you have any idea of why the combination of union types and hashtags could be a problem?

@Jesbjerg Hi, unfortunately no sorry. The fastify and fast-json-stringify libraries are separate libraries to TypeBox, and I only really manage the TypeBox library as a standalone project. As such, I'm not really aware of the downstream updates being applied to fastify and associated libraries (outside of small patches I occasionally submit as an external contributor). The best people to ask would be the fast-json-stringify maintainers (which I believe are the same developers that maintain fastify)

Looking at the error tho, it does appear that fast-json-stringify is appending a double hash on the $id. It's likely doing this to help with schema dereferencing, but isn't expecting users to specify their own # in the $id (hence the double hashing)

Error: no schema with key or ref "urn:test:test:test:test:test#response#/properties/test/anyOf/0"
                                                                       ^ additional append / double hashing
 

I think your best bet here is to remove the #response from your schemas if you can (as it's pretty non-standard to do that, and afaik, the # in the $id has no special meaning and only gets utilized in relative schema deref via $ref).

Still, if you want to let the fast-json-stringify team know, feel free to link back to this issue. They may want to investigate the handling of $id (but I think they will likely suggest removing the #response hash on the $id too :D)

Will close off this issue for now.
Many Thanks!
S