Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: token "definitions" does not exist #524

Closed
2 tasks done
Fdawgs opened this issue Jan 10, 2022 · 10 comments · May be fixed by #676
Closed
2 tasks done

Error: token "definitions" does not exist #524

Fdawgs opened this issue Jan 10, 2022 · 10 comments · May be fixed by #676
Labels
bug Confirmed bug

Comments

@Fdawgs
Copy link
Member

Fdawgs commented Jan 10, 2022

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

3.25.3

Plugin version

4.12.1

Node.js version

16.13.0

Operating system

Windows

Operating system version (i.e. 20.04, 11.3, 10)

10

Description

Upon upgrading from 4.12.0 to ^4.12.1, components.schemas.def-0 is no longer populated with shared schemas/definitions.
This is leading to Invalid reference token: definitions being thrown by Redoc, or token "definitions" does not exist by other validators, when attempting to load the schema.

Steps to Reproduce

This issue is present in Fdawgs/ydh-myydh-crud-api.
The shared schemas are held in a plugin.

4.12.0 example

In v4.12.0 components.schemas.def-0 looks like so:

"def-0": {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "definitions": {
        "unauthorized": {
            "type": "object",
            "title": "401 Unauthorized",
            "properties": {
                "statusCode": {
                    "type": "number",
                    "const": 401
                },
                "error": {
                    "type": "string",
                    "const": "Unauthorized"
                },
                "message": {
                    "type": "string",
                    "examples": ["missing authorization header"]
                }
            }
        },
        "notFoundDbResults": {
            "type": "object",
            "title": "404 Not Found Response",
            "properties": {
                "statusCode": {
                    "type": "number",
                    "const": 404
                },
                "error": {
                    "type": "string",
                    "const": "Not Found"
                },
                "message": {
                    "type": "string",
                    "enum": [
                        "Invalid or expired search results",
                        "Record does not exist or has already been deleted",
                        "User not found"
                    ]
                }
            }
        },
        "notAcceptable": {
            "type": "object",
            "title": "406 Not Acceptable Response",
            "properties": {
                "statusCode": {
                    "type": "number",
                    "const": 406
                },
                "error": {
                    "type": "string",
                    "const": "Not Acceptable"
                },
                "message": {
                    "type": "string",
                    "const": "Not Acceptable"
                }
            }
        },
        "tooManyRequests": {
            "type": "object",
            "title": "429 Too Many Requests Response",
            "properties": {
                "statusCode": {
                    "type": "number",
                    "const": 429
                },
                "error": {
                    "type": "string",
                    "const": "Too Many Requests"
                },
                "message": {
                    "type": "string",
                    "examples": [
                        "Rate limit exceeded, retry in 1 minute"
                    ]
                }
            }
        },
        "internalServerError": {
            "type": "object",
            "title": "500 Internal Server Error Response",
            "properties": {
                "statusCode": {
                    "type": "number",
                    "const": 500
                },
                "error": {
                    "type": "string",
                    "const": "Internal Server Error"
                },
                "message": {
                    "type": "string",
                    "examples": [
                        "Unable to delete read receipt from database",
                        "Unable to return result(s) from database",
                        "Unable to update patient preference in database",
                        "Unable to update read receipt in database"
                    ]
                }
            }
        },
        "serviceUnavailable": {
            "type": "object",
            "title": "503 Service Unavailable",
            "properties": {
                "statusCode": {
                    "type": "number",
                    "const": 503
                },
                "code": {
                    "type": "string",
                    "const": "FST_UNDER_PRESSURE"
                },
                "error": {
                    "type": "string",
                    "const": "Service Unavailable"
                },
                "message": {
                    "type": "string",
                    "const": "Service Unavailable"
                }
            }
        }
    },
    "type": "object",
    "title": "Responses",
    "description": "Common response schemas"
},

^4.12.1 example

When launching the API with any version of fastify-swagger ^4.12.1, components.schemas looks like so:

"schemas": {
    "def-0": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "title": "Responses",
        "description": "Common response schemas"
    },
    "def-1": {
        "type": "object",
        "title": "401 Unauthorized",
        "properties": {
            "statusCode": {
                "type": "number",
                "const": 401
            },
            "error": {
                "type": "string",
                "const": "Unauthorized"
            },
            "message": {
                "type": "string",
                "example": "missing authorization header"
            }
        }
    },
}

As you can see above, it seems the definitions have moved outside of the original def-0 object.
The route schemas still refer to non-existent definitions at def-0:

"406": {
    "description": "Not Acceptable",
    "content": {
      "text/plain": {
        "schema": {
          "$ref": "#/components/schemas/def-0/definitions/notAcceptable",
          "description": "Not Acceptable"
        }
      }
    }
  },

Expected Behavior

$refs to refer to correct definitions, either by adding them back to def-0 or by referring to def-*

@mcollina
Copy link
Member

Would you like to PR a fix?

@Fdawgs
Copy link
Member Author

Fdawgs commented Jan 11, 2022

Would you like to PR a fix?

I can certainly have a go!
#472 was the main change in 3.12.1 so will start there.

@Fdawgs
Copy link
Member Author

Fdawgs commented Jan 11, 2022

Seems that use of definitions was not tested with #472.

Adding the example schema from the Validation and Serialization page of the Fastify docs to the schema shows this a bit more clearly than my initial example:

instance.addSchema({
    $id: 'http://foo/common.json',
    type: 'object',
    definitions: {
    foo: {
        $id: '#address',
        type: 'object',
        properties: {
        city: { type: 'string' }
        }
    }
    }
})

Resulting OpenAPI spec generated:

{
	"def-0": { "type": "object", "title": "http://foo/common.json" },
	"def-1": {
		"type": "object",
		"properties": { "city": { "type": "string" } },
		"title": "#address"
	}
}

Expected result:

{
	"def-0": {
		"type": "object",
		"title": "http://foo/common.json",
		"definitions": {
			"foo": {
				"type": "object",
				"properties": { "city": { "type": "string" } },
				"title": "#address"
			}
		}
	}
}

@mcollina
Copy link
Member

ouch. Could you revert the offending change or send a PR to fix it?

@then3rdman
Copy link

I TIHNK i am running into this exact issue, hwoever im rather confused that this is still an issue considering there has been a major version release since this was raised?

@Fdawgs
Copy link
Member Author

Fdawgs commented Feb 9, 2022

I TIHNK i am running into this exact issue, hwoever im rather confused that this is still an issue considering there has been a major version release since this was raised?

Wrote the wrong major version, have updated the original issue

@then3rdman
Copy link

OK that makes much more sense as to why this is still a known issue

@anbraten

This comment was marked as off-topic.

@Fdawgs
Copy link
Member Author

Fdawgs commented Aug 3, 2022

As a workaround, use properties instead of definitions and then refer to the properties of the shared schema.

instance.addSchema({
	$id: 'http://foo/common.json',
	type: 'object',
	properties: {
		foo: {
			title: 'address',
			type: 'object',
			properties: {
				city: { type: 'string' },
			},
		},
	},
});

Resulting OpenAPI spec generated:

{
	"def-0": {
		"type": "object",
		"title": "http://foo/common.json",
		"properties": {
			"foo": {
				"type": "object",
				"properties": { "city": { "type": "string" } },
				"title": "address"
			}
		}
	}
}

Then in your routes, when referring just point to properties instead:

{
	"home": { "$ref": "http://foo/common.json#/properties/foo" }
}

@mikaelkaron
Copy link

mikaelkaron commented Aug 3, 2022

Love that there's a workaround. Any idea if the underlying issue with definitions will still be addressed in #639?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Confirmed bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants