skip to content

The HTTP status codes 400 Bad Request and 422 Unprocessable Content are both client errors. What does each one mean per the HTTP specifications, and how do generic caches, proxies and clients treat them on the wire?

level: middleimportance: should knowfreq 55%

answer

  1. 400 = the message; 422 = the meaning
  2. 422 born in WebDAV, renamed Content by RFC 9110
  3. 422 presupposes media type understood — else 415
  4. unknown 4xx → client treats it as 400
  5. not cacheable by default, no retry semantics

basics

~20 s

400: the server could not parse or accept the message itself — malformed syntax, framing or unparseable content. 422: the media type was understood and the syntax parsed, but the server cannot process the instructions. Both are client errors; neither is auto-retryable or cacheable by default.

solid answer

~50 s

**400 Bad Request** (RFC 9110 §15.5.1) is defined against the *message*: the server cannot or will not process the request because of "malformed request syntax, invalid request message framing, or deceptive request routing." It can be emitted before any application code runs, and it is the fallback meaning of the whole 4xx class — a client that sees an unknown 4xx must treat it as 400. **422 Unprocessable Content** originated in WebDAV (RFC 2518/4918, then named *Unprocessable Entity*) and was folded into core HTTP by RFC 9110. Its definition has preconditions: the media type was understood (so 415 is wrong) and the content's syntax was correct (so 400 is wrong on syntax grounds), yet the server could not process the contained instructions. On the wire: neither is cacheable by default under RFC 9111, neither carries retry semantics like 429/503, and 422 can only come from something that read the content — usually your application, never a dumb proxy.

code

http · 11 lines
http
POST /v1/orders HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 26

{"qty": 3, "sku": "A-1",

HTTP/1.1 400 Bad Request
Content-Type: application/problem+json

{"title":"Malformed JSON","status":400,"detail":"Unexpected end of input at offset 26"}

go deeper

for a junior

Recall the one-line split: 400 = the server could not read the message; 422 = it read and understood the message but cannot carry out what it says. Both are client errors, so retrying identical bytes will not help.

for a middle

Quote the definitions with their preconditions — RFC 9110's "malformed syntax, framing, or deceptive routing" for 400, and 422's requirement that the media type was understood and the syntax correct. Name the WebDAV origin and the Unprocessable Entity to Unprocessable Content rename.

for a senior

Add the operational wire facts: neither is cacheable by default under RFC 9111, neither has retry semantics, and 400 can be edge-generated while 422 must come from something that parsed the content — a useful first triage signal when reading a trace or an access log.

for a principal

Frame it as a layering property: 400 belongs to the message and framing layer and can be produced by any hop, while 422 is necessarily application-layer and requires content comprehension. That asymmetry drives where you place error observability, what your edge is allowed to reject, and why unknown-4xx-degrades-to-400 keeps generic clients safe.

## The class both codes belong to HTTP status codes are grouped by their first digit. The 4xx class means *client error*: the server believes the fault lies in the request as sent, not in itself. RFC 9110 — the current core HTTP semantics specification, published 2022 — says a server sending a 4xx SHOULD include a representation explaining the error, and that repeating the identical request is not expected to help. 400 and 422 are both members of that class. Everything below is about *which* client error each one names. ## 400 Bad Request — "I could not parse or accept the message itself" RFC 9110 §15.5.1 defines 400 as: the server cannot or will not process the request "due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing)." Three consequences follow from that wording. First, it is about the **message**, not about what the message asks for: a bad request line, a header field that violates field syntax, a `Content-Length` that disagrees with the body, a body that claims to be JSON and is not, a query parameter declared as an integer that arrives as `abc`. Second, it can be emitted **before the server understands the request at all**. You do not need to route to an application handler to know the message is broken. In HTTP/1.1, a framing error leaves the connection in an unrecoverable state, so RFC 9112 requires the server to close the connection after responding — which is why proxy-generated 400s so often carry `Connection: close`. In HTTP/2 and HTTP/3, a genuinely malformed frame is a protocol-level stream or connection error (`RST_STREAM` with `PROTOCOL_ERROR`) rather than a 400 status at all. Third, 400 is the **catch-all** of the class. RFC 9110 tells clients they must understand the *class* of a status code even when the specific code is unknown, and treat an unrecognized 4xx as equivalent to 400. So 400 is simultaneously a specific code and the default meaning of every 4xx a client has never heard of — including 422, to an old enough client. ## 422 Unprocessable Content — "I parsed it; the instructions don't work" 422 started outside core HTTP. WebDAV (RFC 2518, later RFC 4918) needed a code for a request body that was well-formed XML, of an understood content type, but contained instructions the server could not carry out. It was called *Unprocessable Entity*. RFC 9110 promoted it into core HTTP semantics and renamed the reason phrase to **Unprocessable Content** — same code, same meaning, modern wording. Its definition carries three preconditions: the server understood the **media type** of the content (which is why 415 Unsupported Media Type would be the wrong answer), the **syntax** of the content was correct (which is why 400 would be the wrong answer on syntax grounds), and the server was nevertheless **unable to process the contained instructions**. That last clause is the entire code. 422 is a statement about semantics: the request said something the server understood but cannot act on. ## Where the definitional line sits The line is *understanding* versus *acting*. 400 says the server never got far enough to understand what was asked. 422 says it understood exactly what was asked and could not do it. Note that the spec draws this line over the message and its content — it says nothing about business rules, validation frameworks, or which code an API contract should choose for a failed domain check; that selection is a contract-design decision owned by REST status-code selection, not by the wire specification. ## Wire-level facts that hold regardless **Neither is auto-retryable.** Unlike 429 or 503, neither code has retry semantics attached and neither has a conventional `Retry-After`. A generic client that resends identical bytes gets an identical answer. Retry is only meaningful after the request itself changes. **Neither is cacheable by default.** RFC 9111 lists the status codes a cache may store and reuse heuristically without explicit freshness information: 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501. 400 and 422 are absent. A shared cache reuses either one only when the response carries explicit freshness (`Cache-Control: max-age=…`, `Expires`), which almost nothing does. In practice both are one-shot responses. **Their origins differ.** 400 is routinely generated by an intermediary — reverse proxy, load balancer, WAF — for an oversized header block, a bad request line, or a framing violation, so the origin application never sees the request. 422 essentially never comes from an intermediary: producing it requires having understood the media type and inspected the content, which only the application does. That asymmetry is a real debugging tool — a 400 whose body is nginx HTML with `Connection: close` was rejected at the edge; a 400 in your own JSON envelope was rejected by your code. **Neither code carries machine-readable detail by itself.** The status line is three digits; anything a client can branch on lives in the body, for which `application/problem+json` (RFC 9457) is the standard shape.

  • Where does HTTP 415 Unsupported Media Type sit relative to 400 and 422?
    415 says the server refuses the content because its media type or encoding is unsupported — it never attempted to parse it. 422's definition explicitly presupposes that 415 does not apply: the media type *was* understood. So the progression is 415 (wrong format for me), 400 (right format, unreadable bytes), 422 (readable, understood, unactionable).
  • Can a reverse proxy or WAF legitimately return 422 on its own?
    Practically never. Emitting 422 requires having understood the content's media type and confirmed its syntax before failing on the instructions, which means interpreting the body — work a generic intermediary does not do. Proxies overwhelmingly emit 400 for anything they reject, which is why a non-JSON 400 body is a strong signal the request died at the edge.
  • Why is there no Retry-After on 400 or 422, when 429 and 503 have one?
    Retry-After tells a client that the same request may succeed later. For 429 and 503 the obstacle is transient — rate budget or server capacity. For 400 and 422 the obstacle is the request itself: the bytes are malformed, or the instructions are unactionable. Waiting changes nothing, so the specs attach no retry hint and a generic client should not resend unchanged.
  • A client library only knows the original HTTP/1.1 status list and receives a 422. What must it do?
    RFC 9110 requires clients to understand the *class* of any status code and treat an unrecognized code as the x00 of its class — so 422 is handled as 400. That is safe: both are non-retryable client errors, and the client should surface the response body rather than guess at semantics.

400 is the postal service refusing an envelope with an illegible address — it never got opened. 422 is the recipient opening it, reading a perfectly legible letter, and finding it asks for something impossible.

saying these in an interview costs you the question

  • Saying 422 means "validation failed" — the spec says nothing about validation; it says the media type was understood, the syntax was correct, and the instructions could not be processed.
  • Claiming 400 is only for broken JSON. It also covers malformed request lines, illegal header field syntax, and framing errors, and can be emitted before the body is read at all.
  • Believing 422 is a WebDAV-only or non-standard code. RFC 9110 moved it into core HTTP semantics in 2022, renaming the reason phrase to Unprocessable Content.
  • Assuming a client should retry a 400 or 422 with backoff. Neither carries retry semantics; resending identical bytes yields an identical response.
  • Thinking caches happily store 4xx responses. RFC 9111's heuristically cacheable set includes 404, 405, 410 and 414 but not 400 or 422 — those need explicit freshness headers to be reused.
  • Confusing 422 with 415: 422's definition explicitly assumes the media type *was* supported.

context