← Debugging Guides

阅读中文版本

FastAPI — request fails with 422 Unprocessable Entity

Read FastAPI 422 validation error responses to find which field and rule rejected the request body.

beginnerdebuggingpythonfastapi

Symptoms

  • The endpoint returns 422 instead of the expected 200
  • The response body contains a detail array with loc, msg and type
  • curl works but the browser or client fails
  • Valid-looking JSON is rejected, sometimes due to a type mismatch

Possible causes

  • A request field is missing, null or of the wrong type relative to the Pydantic model
  • A body is sent without the correct Content-Type header
  • A value violates a constraint such as minimum length or a pattern
  • The client sends form data where the endpoint expects JSON, or vice versa

Diagnosis steps

Read the detail array in the response

curl -i -X POST http://localhost:8000/items -H "Content-Type: application/json" -d '{}'

Interpretation

Each entry names the location path in loc, the rule in type and a human message in msg. This pinpoints the offending field.

Reproduce with the exact content type

curl -i -X POST http://localhost:8000/items -H "Content-Type: application/json" -d '{"name":"x","price":1}'

Interpretation

If this succeeds while the client fails, the client is not sending the header or is serializing the body incorrectly.

Check the Pydantic model constraints

grep -n "Field(" app/schemas.py

Interpretation

Constraints such as gt, min_length and regex explain rejections that look valid from the raw values.

Root cause

FastAPI validates the request against the Pydantic model before the handler runs. The 422 means the parsed data failed a type or constraint check, so the request never reached your endpoint code.

Fix

Align the client payload with the model by adding missing fields, fixing types and sending the correct content type, or relax the model constraints if the contract should accept the value.

Verify the fix

Resend the request and confirm a 2xx status with the expected body. Add a test that posts a representative payload so future schema changes are caught.

Symptom walkthrough

A client posts what looks like valid data yet receives HTTP 422 Unprocessable Entity. The JSON response carries a detail array whose entries include a location, a message and a type identifier. Because validation happens before the endpoint function, no application logging appears, which confuses developers expecting a server error in the logs.

Fix in practice

Compare the payload with the Pydantic model, add any missing required fields, correct the types, and ensure the request sets Content-Type application/json. If the contract itself is wrong, adjust the model and its constraints instead of loosening validation blindly.

Verification

Repeat the request and confirm a 2xx response with the expected content. Add an automated test posting a representative payload so that future model changes surface as test failures rather than production 422s. Running that suite on every change is the habit that keeps the contract protected.

Diagnostic commands

Check the behavior with commands like these:

curl -i -X POST http://localhost:8000/items -H "Content-Type: application/json" -d '{}'
curl -i -X POST http://localhost:8000/items -H "Content-Type: application/json" -d '{"name":"x","price":1}'
grep -n "Field(" app/schemas.py