Skip to content
Latchkey

FastAPI "RequestValidationError" / pydantic 422 on request body in CI

FastAPI validates request bodies against the endpoint's pydantic model and returns 422 with a RequestValidationError when they do not match. A test that posts a payload the model rejects (missing field, wrong type) fails on the status code.

What this error means

A TestClient call asserts 200 but gets 422, with a body listing pydantic validation errors like "field required" or "Input should be a valid integer."

python
assert response.status_code == 200
E    assert 422 == 200
# body:
{"detail":[{"type":"missing","loc":["body","email"],"msg":"Field required"}]}

Common causes

The test payload omits a required field

The pydantic model marks a field required, but the test body does not include it, so validation fails with "Field required".

A type mismatch between payload and model

The body sends a string where the model expects an int (or similar), so pydantic rejects it before the handler runs.

How to fix it

Match the payload to the model

  1. Read the 422 detail to see which field and rule failed.
  2. Build the test body from the same pydantic model to stay in sync.
  3. Assert on the validation detail when you are testing the 422 path deliberately.
python
from app.schemas import UserCreate
payload = UserCreate(email="a@b.com", age=30).model_dump()
r = client.post("/users", json=payload)
assert r.status_code == 201

Test the failure path explicitly

When the 422 is expected, assert the status and the error type instead of a 200.

python
r = client.post("/users", json={})
assert r.status_code == 422
assert r.json()["detail"][0]["type"] == "missing"

How to prevent it

  • Build request payloads from the same pydantic schema the endpoint uses.
  • Keep test fixtures updated when a model adds required fields.
  • Assert on validation detail for negative-path tests.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →