openai/openai-python · error · ValueError
Expected `$ref: {ref}` to resolved to a dictionary but got {
Error message
Expected `$ref: {ref}` to resolved to a dictionary but got {resolved} What it means
While inlining $ref entries for strict mode, the resolved target looked up in the root schema was not a dictionary. This indicates a structurally malformed or self-inconsistent JSON schema, not user input error per se.
Source
Thrown at src/openai/lib/_pydantic.py:106
# strip `None` defaults as there's no meaningful distinction here
# the schema will still be `nullable` and the model will default
# to using `None` anyway
if json_schema.get("default", NOT_GIVEN) is None:
json_schema.pop("default")
# we can't use `$ref`s if there are also other properties defined, e.g.
# `{"$ref": "...", "description": "my description"}`
#
# so we unravel the ref
# `{"type": "string", "description": "my description"}`
ref = json_schema.get("$ref")
if ref and has_more_than_n_keys(json_schema, 1):
assert isinstance(ref, str), f"Received non-string $ref - {ref}"
resolved = resolve_ref(root=root, ref=ref)
if not is_dict(resolved):
raise ValueError(f"Expected `$ref: {ref}` to resolved to a dictionary but got {resolved}")
# properties from the json schema take priority over the ones on the `$ref`
json_schema.update({**resolved, **json_schema})
json_schema.pop("$ref")
# Since the schema expanded from `$ref` might not have `additionalProperties: false` applied,
# we call `_ensure_strict_json_schema` again to fix the inlined schema and ensure it's valid.
return _ensure_strict_json_schema(json_schema, path=path, root=root)
return json_schema
def resolve_ref(*, root: dict[str, object], ref: str) -> object:
if not ref.startswith("#/"):
raise ValueError(f"Unexpected $ref format {ref!r}; Does not start with #/")
path = ref[2:].split("/")
resolved = root
for key in path:View on GitHub (pinned to 9917c6e28e)
Solutions
- Upgrade pydantic to the latest v2 patch
- Simplify nested generic models that trigger unusual $ref layouts
- Print model_json_schema() and verify every $ref resolves to an object node under #/definitions or #/$defs
Example fix
# before
class Inner(BaseModel): ...
class Outer(BaseModel):
inner: Inner | list[Inner] | int # complex union producing odd refs
# after
class Outer(BaseModel):
inners: list[Inner] Defensive patterns
Strategy: validation
Validate before calling
schema = Output.model_json_schema()
def refs_resolve(node, root):
if isinstance(node, dict):
if "$ref" in node and not isinstance(node.get("$ref"), str):
return False
return all(refs_resolve(v, root) for v in node.values())
return not isinstance(node, (list,)) or all(refs_resolve(v, root) for v in node)
assert refs_resolve(schema, schema) Prevention
- Avoid deeply nested generics/unions of models
- Pin recent pydantic v2 versions
- Add a schema-generation smoke test per output model
When it happens
Trigger: A model whose schema has a $ref pointing at a non-object location (e.g. refs into arrays or scalar positions), or schemas mutated/corrupted between generation and strictification.
Common situations: Custom CoreSchema manipulation; pydantic version quirks generating unusual refs; nested generics with older pydantic 2.x versions.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Non BaseModel types are only supported with Pydantic v2 - {m
- Expected {json_schema} to be a dictionary; path={path}
- Unexpected $ref format {ref!r}; Does not start with #/
- Pydantic models must subclass our base model type, e.g. `fro
- mode must be either 'json' or 'python'
AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28).
Data as JSON: /api/errors/a0e15352b22c5136.
Report an issue: GitHub.