Version observed: 0.56.1
Python: 3.14.4
Pydantic target: v2
Severity: generated types are silently incomplete — no error or warning
When a JSON Schema (Draft-07) object has both a top-level allOf and a
top-level oneOf, codegen 0.56.1 emits a class that inherits from the
allOf-derived base but silently drops every oneOf branch. No error,
no warning — just an incomplete model. The expected output is either a
discriminated-union root model (each variant inheriting the allOf base) or
at minimum a clear failure that signals codegen can't represent the shape.
Minimal reproduction
base.json (the allOf target):
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Envelope",
"type": "object",
"properties": {
"version": { "type": "string" }
}
}
response.json (the schema codegen mis-handles):
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Response",
"type": "object",
"allOf": [
{ "$ref": "base.json" }
],
"oneOf": [
{
"title": "Success",
"properties": {
"status": { "type": "string", "const": "success" },
"data": { "type": "string" }
},
"required": ["status", "data"]
},
{
"title": "Error",
"properties": {
"status": { "type": "string", "const": "error" },
"message": { "type": "string" }
},
"required": ["status", "message"]
}
],
"properties": {}
}
Invocation:
datamodel-codegen \
--input ./schemas \
--input-file-type jsonschema \
--output-model-type pydantic_v2.BaseModel \
--output ./generated
Actual output (response.py)
from .base import Envelope
class Response(Envelope):
pass
The four-branch discriminated union is gone.
Expected output
Something equivalent to:
from pydantic import RootModel
from .base import Envelope
class ResponseSuccess(Envelope):
status: Literal["success"]
data: str
class ResponseError(Envelope):
status: Literal["error"]
message: str
class Response(RootModel[ResponseSuccess | ResponseError]):
root: Annotated[ResponseSuccess | ResponseError, Field(discriminator="status")]
Real-world impact
This pattern shows up in 31 response schemas in the AdCP protocol
(adcontextprotocol/adcp 3.1.0-beta.1) — every response that wraps a
version envelope and returns a discriminated success/error union.
Downstream consumers see the schema-declared variant shapes go missing
from generated types, with no diagnostic — the failure surfaces much later
as AttributeError / KeyError at runtime when callers reach for fields
the codegen dropped.
The workaround we ended up applying in a prep step rewrites the schema
before passing it to codegen: merge the allOf branch properties into
each oneOf branch, then delete the top-level allOf. That produces
correct output, but only because we have a controlled prep pipeline —
SDK adopters who just run datamodel-codegen against vendor schemas
have no equivalent escape hatch.
Suggested fix paths
Two options that would both be acceptable, in priority order:
- Generate the discriminated union, treating
allOf as additional base
fields per branch. Each oneOf branch class inherits the allOf-derived
base; the top-level type is a RootModel union. Matches author intent
and standard JSON Schema semantics.
- Emit a hard error. If (1) is implementation-prohibitive, at minimum
refuse to generate and tell the user the shape isn't supported. The
silent drop is the worst failure mode here.
Environment
- Python 3.14.4 (also reproduces on 3.10–3.13)
datamodel-code-generator==0.56.1
- pydantic 2.12.x
- Schemas: Draft-07
- macOS 14 / Linux x86_64 — same behavior on both
Happy to provide the full 31-schema-tree reproduction if useful.
Version observed: 0.56.1
Python: 3.14.4
Pydantic target: v2
Severity: generated types are silently incomplete — no error or warning
When a JSON Schema (Draft-07) object has both a top-level
allOfand atop-level
oneOf, codegen 0.56.1 emits a class that inherits from theallOf-derived base but silently drops every
oneOfbranch. No error,no warning — just an incomplete model. The expected output is either a
discriminated-union root model (each variant inheriting the allOf base) or
at minimum a clear failure that signals codegen can't represent the shape.
Minimal reproduction
base.json(theallOftarget):{ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Envelope", "type": "object", "properties": { "version": { "type": "string" } } }response.json(the schema codegen mis-handles):{ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Response", "type": "object", "allOf": [ { "$ref": "base.json" } ], "oneOf": [ { "title": "Success", "properties": { "status": { "type": "string", "const": "success" }, "data": { "type": "string" } }, "required": ["status", "data"] }, { "title": "Error", "properties": { "status": { "type": "string", "const": "error" }, "message": { "type": "string" } }, "required": ["status", "message"] } ], "properties": {} }Invocation:
Actual output (response.py)
The four-branch discriminated union is gone.
Expected output
Something equivalent to:
Real-world impact
This pattern shows up in 31 response schemas in the AdCP protocol
(
adcontextprotocol/adcp3.1.0-beta.1) — every response that wraps aversion envelope and returns a discriminated success/error union.
Downstream consumers see the schema-declared variant shapes go missing
from generated types, with no diagnostic — the failure surfaces much later
as
AttributeError/KeyErrorat runtime when callers reach for fieldsthe codegen dropped.
The workaround we ended up applying in a prep step rewrites the schema
before passing it to codegen: merge the
allOfbranch properties intoeach
oneOfbranch, then delete the top-levelallOf. That producescorrect output, but only because we have a controlled prep pipeline —
SDK adopters who just run
datamodel-codegenagainst vendor schemashave no equivalent escape hatch.
Suggested fix paths
Two options that would both be acceptable, in priority order:
allOfas additional basefields per branch. Each oneOf branch class inherits the allOf-derived
base; the top-level type is a RootModel union. Matches author intent
and standard JSON Schema semantics.
refuse to generate and tell the user the shape isn't supported. The
silent drop is the worst failure mode here.
Environment
datamodel-code-generator==0.56.1Happy to provide the full 31-schema-tree reproduction if useful.