openai/openai-python · error · ValueError
Unexpected $ref format {ref!r}; Does not start with #/
Error message
Unexpected $ref format {ref!r}; Does not start with #/ What it means
resolve_ref only supports local JSON Schema references of the form '#/...'. A $ref that is an external URL or anchor (e.g. 'http://...', '#name') is rejected because strict-mode schema inlining cannot resolve it.
Source
Thrown at src/openai/lib/_pydantic.py:120
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:
value = resolved[key]
assert is_dict(value), f"encountered non-dictionary entry while resolving {ref} - {resolved}"
resolved = value
return resolved
def is_basemodel_type(typ: type) -> TypeGuard[type[pydantic.BaseModel]]:
if not inspect.isclass(typ):
return False
return issubclass(typ, pydantic.BaseModel)
def is_dataclass_like_type(typ: type) -> bool:View on GitHub (pinned to 9917c6e28e)
Solutions
- Remove or inline the external-referencing types into your own models
- Ensure all referenced types are local pydantic v2 models so refs stay '#/$defs/...'
- If hand-building a schema, replace remote refs with inlined definitions
Example fix
# before
class Output(BaseModel):
x: ExternalLibType # emits external $ref
# after
class LocalType(BaseModel):
... # copy fields locally
class Output(BaseModel):
x: LocalType Defensive patterns
Strategy: validation
Validate before calling
schema = Output.model_json_schema()
import json
text = json.dumps(schema)
import re
ext = re.findall(r'"\$ref"\s*:\s*"(?!#/)', text)
assert not ext, f"external refs detected: {ext}" Prevention
- Only reference local pydantic models in output types
- Avoid importing types from libs that declare external JSON-schema ids
When it happens
Trigger: A pydantic model (or custom schema) that emits external $refs, e.g. referencing types from another library that set external $id/$schema URLs.
Common situations: Models importing types from packages that declare external JSON schema ids; hand-written schemas with remote refs; pydantic v1 generating absolute-ref schemas from certain configurations.
Related errors
- Expected `$ref: {ref}` to resolved to a dictionary but got {
- Non BaseModel types are only supported with Pydantic v2 - {m
- Expected {json_schema} to be a dictionary; path={path}
- 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/e20b5beaacd36beb.
Report an issue: GitHub.