Return 400 when the server cannot read the request. Return 422 when the server can read it, but the data inside is invalid.
400 Bad Request is for requests the server cannot or will not process because of a client error, such as broken syntax. Examples:
- invalid JSON
- a missing required header
- a query parameter in the wrong form
422 Unprocessable Content means the server understands the content type and the body has correct syntax. But the server cannot process the instructions in it. RFC 9110 renamed it from "Unprocessable Entity". Typical cases are validation failures:
- an email field that is not an email
- an end date before the start date
- a quantity of -3
In practice, many frameworks return 400 for validation errors. NestJS's ValidationPipe does this by default, and you can change it with the errorHttpStatusCode option. Either choice is fine if the API is consistent and the response body explains which fields failed.
- 400 means the request is malformed and the server cannot parse it.
- 422 means the request is well-formed, but its meaning is invalid.
- RFC 9110 names 422 "Unprocessable Content".
- Consistency and a clear error body matter more than the exact choice.