Improper handling of type compatibility in allOf clauses for OpenAPI 3.1 Spec
Since OpenAPI 3.1, the type schema field can now be a list, for example:
"type": ["string", "null"]
Would mean that the schema can be a string or null.
Redoc verifies that when "overriding" a property with allOf, the type is identical (see here). But the check is done using ===, which does not work well for lists, hence I'm getting this error:
Incompatible types in allOf at "/properties/error/properties/code": "string,null" and "string,null"
Expected behavior
If both types in the parent and child schema are ["string", "null"], there shouldn't be an error.
The solution is probably to modify the comparison to be smarter than a simple ===.
share your schema or a repro
Oh, thought I had, my bad.
{
"openapi": "3.1.0",
"info": {
"title": "Cars",
"version": "1.0"
},
"paths": {
"/test": {
"get": {
"operationId": "testGet",
"responses": {
"200": {
"description": "default response",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/Union"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Union": {
"type": "object",
"oneOf": [
{
"$ref": "#/components/schemas/Porsche"
},
{
"$ref": "#/components/schemas/PorscheGT3"
}
]
},
"Porsche": {
"type": "object",
"properties": {
"name": {
"type": [
"string",
"null"
]
}
}
},
"PorscheGT3": {
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/Porsche"
},
{
"properties": {
"name": {
"type": [
"string",
"null"
],
"const": "Porsche GT3"
},
"weissach": {
"type": "boolean"
}
}
}
]
}
}
}
}
Of course this is just a simple example, my actual schemas are much more complex, but the problem is well represented here. The overriding of the "name" property results in the following error:
Incompatible types in allOf at "#/components/schemas/Union/oneOf/1/properties/name": "string,null" and "string,null"
Can you share the command you are using?
I tried here on version 2.8 and it doesn't seem to have any issue building the preview command with --product redoc
redocly preview -d ./redocly --product redoc -p 5501
Separately, your schema is potentially invalid the way you have defined it.
The oneOf must match only one(XOR) schema and it currently has the ability to pass both oneOf subschemas with the following example:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"oneOf": [
{
"$ref": "#/$defs/Porsche"
},
{
"$ref": "#/$defs/PorscheGT3"
}
],
"$defs": {
"Porsche": {
"type": "object",
"properties": {
"name": {
"type": ["string", "null"]
}
}
},
"PorscheGT3": {
"type": "object",
"allOf": [
{
"$ref": "#/$defs/Porsche"
}
],
"properties": {
"name": {
"type": ["string", "null"],
"const": "Porsche GT3"
},
"weissach": {
"type": "boolean"
}
}
}
}
}
With this instance
{
"name": "Porsche GT3",
"weissach": true
}
the name attribute matches both subschemas.
Because the const value is a string, it will always match oneOf/0. The allOf is causing you unnecessary problems here. Remove that and add a pattern to constrain the GT3 value
"Porsche": {
"type": "object",
"properties": {
"name": {
"type": ["string", "null"],
"pattern": "^.+(?<!GT3)$" //negative lookbehind to constrain the GT3 value only to the second subschema
}
}
},
"PorscheGT3": {
"type": "object",
"properties": {
"name": {
"type": ["string", "null"],
"const": "Porsche GT3"
},
"weissach": {
"type": "boolean"
}
}
}
if you want to post your schemas, I can review them to look over how you have defined some of these patterns.