Description
Prerequisites
- I have written a descriptive issue title
- I have searched existing issues to ensure the bug has not already been reported
Fastify version
4.23.2
Plugin version
No response
Node.js version
18.12.1
Operating system
Windows
Operating system version (i.e. 20.04, 11.3, 10)
11
Description
The following error is thrown when validating a response using a response schema, when trying to return a response:
{
"statusCode": 500,
"error": "Internal Server Error",
"message": "can't resolve reference #/definitions/Type from id merged_45bedfdc-0c19-4649-8739-66c2f819bb2e"
}
This is unexpected: it's my understanding that schemas should be validated on server startup.
The error also does not throw if the response does not include the problematic parts of the schema.
This is most likely an AJV bug, but I was not able to reproduce it trivially. I would appreciate help with isolating the Fastify-AJV interaction to reproduce this without the Fastify server at all.
Steps to Reproduce
Full sample code:
import Fastify from "fastify";
const schema = {
$schema: "http://json-schema.org/draft-07/schema#",
title: "Schema Response",
type: "object",
required: [],
properties: {
types: {
description: "A list of types.",
type: "object",
additionalProperties: {
$ref: "#/definitions/Type",
},
},
},
definitions: {
Type: {
title: "Type",
description: "Types track the valid representations of values as JSON",
oneOf: [
{
description: "A named type",
type: "object",
required: ["name", "type"],
properties: {
name: {
description:
"The name can refer to a primitive type or a scalar type",
type: "string",
},
type: {
type: "string",
enum: ["named"],
},
},
},
{
description: "A nullable type",
type: "object",
required: ["type", "underlying_type"],
properties: {
type: {
type: "string",
enum: ["nullable"],
},
underlying_type: {
description: "The type of the non-null inhabitants of this type",
allOf: [
{
$ref: "#/definitions/Type",
},
],
},
},
},
],
},
},
};
const data = {
types: {
Int: {
type: "named",
name: "Int",
},
NullableString: {
type: "nullable",
underlying_type: {
type: "named",
name: "String",
},
},
},
};
async function start_server() {
const server = Fastify({
logger: true,
});
server.get(
"/",
{
schema: {
response: {
200: schema,
},
},
},
() => {
return data;
}
);
try {
await server.listen({ port: 3030 });
} catch (error) {
server.log.error(error);
process.exit(1);
}
}
start_server();
Fastify version: 4.23.2
To reproduce the error, run the server, and perform a GET request against it.
Expected Behavior
The response should be validated successfully, or it should fail to validate, but not fail to resolve the validation schema, except on server startup.
Note, the following using only AJV does not error:
const schema = { /* same as above */ }
const data = { /* same as above */ }
const validate = ajv.compile(schema);
const valid = validate(data);
if (!valid) {
console.log("validation failed");
console.log(validate.errors);
} else {
console.log("validation succeeded");
}
I strongly suspect this is an AJV issue, but as the above did not repro the problem I would appreciate any help in isolating the issue.
Workarounds
I've observed two ways to avoid this issue:
- use
$recursiveRef
instead of$ref
. I don't believe this is the correct use case for$recursiveRef
, but it does make the problem go away - specify an
$id
on the root, then qualify$refs
with the id before the#
Possibly related issues
Using discriminator in a definition causes failure to compile if oneOf contains a reference fastify/fastify#1899
Is it possible to create a recursive schema definition? fastify/fastify#659