422 Unprocessable Content vs 400 Bad Request
Use 400 when the server cannot parse or understand the request, such as broken JSON or a bad header. Use 422 when the request is well-formed but the content fails validation, such as a missing required field or an invalid email.
The request is well-formed, but its content fails validation or business rules.
Called "Unprocessable Entity" in WebDAV (RFC 4918), which introduced it; RFC 9110 adopted it under the new name. Frameworks such as Rails and FastAPI use it for validation errors: valid JSON with a missing field, a value out of range, or an email in the wrong format. The body should list which fields failed and why.
The server will not process the request because something in it is malformed.
The catch-all client error: invalid JSON, a broken header, an illegal character in the URL, a missing required parameter. Because it is so broad, a useful 400 response explains what was wrong in the body. If a browser gets a 400 on every page of a site, an oversized or corrupt cookie is a frequent cause; clearing the site's cookies is a quick test.
Explained
422 began in WebDAV (RFC 4918) as "Unprocessable Entity". RFC 9110 made it a general HTTP code and renamed it "Unprocessable Content" (section 15.5.21). Its point is that syntax and content type are both fine; the server just cannot act on what was said.
Example: {"email": "bob@" with no closing brace is a 400, because the body is not valid JSON. {"email": "bob@"} is valid JSON with an invalid value: 422. A body sent as text/plain to a JSON-only endpoint is a 415.
Either code is acceptable for validation errors, and many large APIs use 400 for everything. What matters more is consistency and a body that tells the client which fields failed. RFC 9457 (Problem Details) defines a standard JSON shape for that.
How to debug it
- Check the response body; validation errors usually list the failing fields.
- Confirm the request's
Content-Typematches the body you are sending. - Validate the JSON itself (for example with
jq . < body.json) to rule out a 400 from a syntax error. - Compare field names and types with the API schema; a string where a number is expected is a common 422.
Gotchas
- FastAPI returns 422 for any request that fails its Pydantic models, including wrong types in query parameters, which surprises clients expecting 400.
- A state conflict, such as a duplicate username, is closer to 409 than to 422.
- Do not use 500 for invalid input; it hides client errors in your server error metrics.
Related explainers
- 409 Conflict409 means the request clashes with the resource's current state: a duplicate key or a concurrent edit....
- 401 Unauthorized vs 403 Forbidden401 means the server does not know who you are; 403 means it knows and still says no. How to tell them...
- 500 Internal Server ErrorA 500 is the server's generic failure code, usually an unhandled exception. Where to find the real error...