FastAPI — request fails with 422 Unprocessable Entity
Read FastAPI 422 validation error responses to find which field and rule rejected the request body.
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.pyInterpretation
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