tiangolo/fastapi · error · PydanticV1NotSupportedError
pydantic.v1 models are no longer supported by FastAPI…
Error message
pydantic.v1 models are no longer supported by FastAPI. Please update the model {obj!r}. What it means
PydanticV1NotSupportedError raised inside jsonable_encoder (encoders.py:342). When FastAPI walks the response to serialize it, is_pydantic_v1_model_instance(obj) returns True for a legacy pydantic.v1.BaseModel instance, and FastAPI (which is pydantic-v2-only) refuses to encode it. The message names the offending model via {obj!r}.
Solutions
- Migrate the model to pydantic v2: change `from pydantic import BaseModel` (drop the .v1), and adapt validators/config to v2 (model_config, @field_validator).
- If you must keep a v1 model, convert it before returning: return obj.dict() (v1) or pydantic_v1 parse to a v2 model.
- Search the codebase for `pydantic.v1` imports and remove/replace them.
- Ensure third-party objects returned are v2 models or plain dataclasses/dicts.
Example fix
// before
from pydantic.v1 import BaseModel
class Item(BaseModel):
name: str
@app.get("/items/{i}", response_model=Item)
def read(i: int):
return Item(name="x") # -> PydanticV1NotSupportedError
// after
from pydantic import BaseModel, ConfigDict
class Item(BaseModel):
model_config = ConfigDict()
name: str
@app.get("/items/{i}", response_model=Item)
def read(i: int):
return Item(name="x") Defensive patterns
Strategy: type-guard
Validate before calling
# Reject pydantic v1 models before they reach jsonable_encoder
try:
from pydantic.v1 import BaseModel as V1Model
except ImportError:
V1Model = None
def assert_v2(obj):
if V1Model is not None and isinstance(obj, V1Model):
raise TypeError(f"pydantic v1 model not supported: {obj!r}")
return obj Type guard
def is_pydantic_v1(obj) -> bool:
try:
from pydantic.v1 import BaseModel as V1Model
except ImportError:
return False
return isinstance(obj, V1Model) Try / catch
from fastapi.encoders import jsonable_encoder
try:
data = jsonable_encoder(obj)
except Exception as e:
if "pydantic.v1" in str(e):
data = obj.dict() # v1 fallback, then migrate
else:
raise Prevention
- Migrate all models to pydantic v2 and remove every `pydantic.v1` import.
- Return pydantic v2 models or plain dicts/lists from endpoints.
- Add a CI grep for `pydantic.v1` to block regressions.
- Audit third-party return values to ensure they are v2 models.
When it happens
Trigger: An endpoint returns (or a response_model produces) an instance of a pydantic.v1 model — e.g. a model imported from pydantic.v1, a third-party object built on v1, or code that still uses the v1 compatibility shim — and jsonable_encoder tries to serialize it.
Common situations: Migrating from FastAPI 0.99 (pydantic v1) to 0.100+/1.x (pydantic v2) without converting models; a dependency/library returning pydantic.v1 objects; mixing `from pydantic.v1 import BaseModel` leftovers; ORJSONResponse/custom encoder receiving a v1 model.
Related errors
- pydantic.v1 models are no longer supported by FastAPI…
- {errors}
- {"errors": exc.errors(), "body": body.decode()}
- {"errors": exc.errors(), "body": body.decode()}
- Expected UploadFile, received
AI-assisted analysis of tiangolo/fastapi@3e8d1526d8 (2026-08-11).
Data as JSON: /api/errors/bc673065736fdc29.
Report an issue: GitHub.
Appendix: source
Thrown at fastapi/encoders.py:342
include=include,
exclude=exclude,
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,
exclude_none=exclude_none,
custom_encoder=custom_encoder,
sqlalchemy_safe=sqlalchemy_safe,
)
)
return encoded_list
if type(obj) in ENCODERS_BY_TYPE:
return ENCODERS_BY_TYPE[type(obj)](obj)
for encoder, classes_tuple in encoders_by_class_tuples.items():
if isinstance(obj, classes_tuple):
return encoder(obj)
if is_pydantic_v1_model_instance(obj):
raise PydanticV1NotSupportedError(
"pydantic.v1 models are no longer supported by FastAPI."
f" Please update the model {obj!r}."
)
try:
data = dict(obj)
except Exception as e:
errors: list[Exception] = []
errors.append(e)
try:
data = vars(obj)
except Exception as e:
errors.append(e)
raise ValueError(errors) from e
return jsonable_encoder(
data,
include=include,
exclude=exclude,
by_alias=by_alias,View on GitHub (pinned to 3e8d1526d8)