HTTP 422 Unprocessable Content

Unprocessable Content

HTTP 422 is Unprocessable Content: the server understands the content type and the body parses, but it can’t act on what the body says. RFC 9110 section 15.5.21 gives the example of well-formed XML with semantically wrong instructions; in JSON APIs it’s the usual answer to a validation failure. WebDAV’s RFC 4918 introduced it as Unprocessable Entity, and RFC 9110 brought it into core HTTP in 2022 under the new name.

The exchange

POST /api/orders HTTP/1.1
Content-Type: application/json

{"sku": "duck-07", "qty": -2, "email": "not-an-email"}

HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json

{"type": "https://example.com/probs/validation", "title": "Invalid order", "status": 422,
 "errors": [{"field": "qty", "message": "must be at least 1"},
            {"field": "email", "message": "is not an email address"}]}

RFC 9457 problem details allow extension members like errors. Name every failing field, so the client can mark them all at once. Resending the same body gets the same answer; the client has to change the input.

422 or its neighbours

body doesn't parse, or the framing is broken      400 Bad Request
a Content-Type the endpoint doesn't accept        415 Unsupported Media Type
parses, but values break the rules                422 Unprocessable Content
valid, but clashes with stored state              409 Conflict

RFC 9110’s 400 covers any client error, so 400 for validation isn’t wrong, and Stripe’s and Google’s APIs work that way. 422 is the more specific choice, and FastAPI, Rails and Laravel default to it. Pick one per API and document it. 422 isn’t heuristically cacheable.

Who sends it

  • FastAPI, for any request that fails its Pydantic model, with a detail list of errors. It answers 422 even when the body isn’t valid JSON, where most APIs would send 400.
  • Rails, whose generated controllers render a failed form with a 422. Turbo needs a 4xx or 5xx there to show the errors instead of expecting a redirect.
  • Laravel, for a failed validation on a JSON request.
  • GitHub’s REST API, as Validation Failed.

The old name in code

Unprocessable Entity survives in constants such as Go’s http.StatusUnprocessableEntity and Python’s HTTPStatus.UNPROCESSABLE_ENTITY. Both are 422. Search unprocessable entity in the tool below and it finds 422 through its former phrase.

In your stack

class Order(BaseModel):         # FastAPI answers 422 when qty is below 1
    sku: str
    qty: int = Field(ge=1)
const errors = validateOrder(req.body);
if (errors.length > 0) return res.status(422).json({ errors });   // Express
w.Header().Set("Content-Type", "application/problem+json")
w.WriteHeader(http.StatusUnprocessableEntity)
json.NewEncoder(w).Encode(problem)

Try it in the HTTP Status Codes

422 Unprocessable Content

  1. 422Unprocessable Content4xx Client error

    The request was understood and its syntax is fine, but it cannot be acted on: the fields are there and their values are wrong.

    When to use it

    Validation failures in an API — the classic answer to a body that parses but makes no sense.

    Common mistakes

    Confusing it with 400, which is about syntax, and with 409, which is about state, and leaving out which fields were at fault.

    Not cacheable by defaultRFC 9110Formerly Unprocessable Entity

Every code, by class

Codes marked unofficial come from one server’s own convention — nginx, Cloudflare, cPanel, Microsoft — and are not in the IANA registry.

Runs in your browser. Nothing you enter is sent anywhere.