tiangolo/fastapi · error · ResponseValidationError

{n} validation error(s): {errors}

Error message

{n} validation error(s):
{errors}

What it means

ResponseValidationError raised by serialize_response (routing.py:324) when validating the endpoint's return value against the declared response_model field. The shared message comes from ValidationException.__str__ ('{n} validation error(s):\n{errors}'); errors are the pydantic validation errors produced by field.validate(response_content, ..., loc=("response",)). It surfaces as an HTTP 500 because the response the code produced does not match the response_model contract.

Source

Thrown at fastapi/routing.py:324

    exclude: IncEx | None = None,
    by_alias: bool = True,
    exclude_unset: bool = False,
    exclude_defaults: bool = False,
    exclude_none: bool = False,
    is_coroutine: bool = True,
    endpoint_ctx: EndpointContext | None = None,
    dump_json: bool = False,
) -> Any:
    if field:
        if is_coroutine:
            value, errors = field.validate(response_content, {}, loc=("response",))
        else:
            value, errors = await run_in_threadpool(
                field.validate, response_content, {}, loc=("response",)
            )
        if errors:
            ctx = endpoint_ctx or EndpointContext()
            raise ResponseValidationError(
                errors=errors,
                body=response_content,
                endpoint_ctx=ctx,
            )
        serializer = field.serialize_json if dump_json else field.serialize
        return serializer(
            value,
            include=include,
            exclude=exclude,
            by_alias=by_alias,
            exclude_unset=exclude_unset,
            exclude_defaults=exclude_defaults,
            exclude_none=exclude_none,
        )

    else:
        return jsonable_encoder(response_content)

View on GitHub (pinned to 3e8d1526d8)

Solutions

  1. Make the endpoint return data that matches response_model (correct types, required fields present).
  2. Loosen the response_model where appropriate: Optional fields, Union, or response_model_exclude_none.
  3. Convert ORM objects with from_attributes=True (model_config) or build the response model explicitly.
  4. Reproduce under TestClient and read the per-field errors in the 500 response body to fix the mismatch.

Example fix

// before
class HeroOut(BaseModel):
    id: int
    name: str
    age: int  # required

@app.get("/heroes/{i}", response_model=HeroOut)
def read(i: int):
    return {"id": i, "name": "x"}  # missing age -> ResponseValidationError

// after
class HeroOut(BaseModel):
    id: int
    name: str
    age: int | None = None

@app.get("/heroes/{i}", response_model=HeroOut)
def read(i: int):
    return {"id": i, "name": "x"}
Defensive patterns

Strategy: validation

Validate before calling

# Validate the endpoint return against response_model in a unit test
from fastapi.testclient import TestClient
from app import app, HeroOut

def test_read_hero_matches_response_model():
    client = TestClient(app)
    r = client.get("/heroes/1")
    assert r.status_code == 200
    HeroOut.model_validate(r.json())  # raises if shape mismatches response_model

Try / catch

from fastapi.exceptions import ResponseValidationError
from fastapi.testclient import TestClient

client = TestClient(app, raise_server_exceptions=False)
r = client.get("/heroes/1")
if r.status_code == 500 and "validation error" in r.text:
    # inspect r.json()['detail'] for the failing response fields
    print(r.text)

Prevention

When it happens

Trigger: An endpoint returns data that fails validation against its response_model — e.g. returning None where the model requires fields, returning an int where a str is declared, extra/missing fields with strict mode, a nested object that does not coerce to the model, or an ORM object that does not map onto the response_model.

Common situations: Changing the response_model without updating the endpoint return; returning a raw ORM row whose fields do not match the schema; a DB null landing on a required response field; stricter pydantic v2 validation after an upgrade; returning a wrong-shaped dict from a helper.

Related errors


AI-assisted analysis of tiangolo/fastapi@3e8d1526d8 (2026-08-11). Data as JSON: /api/errors/2dd261a1d0e75523. Report an issue: GitHub.