400 vs 422: Bad Request vs Unprocessable Content

400 Bad Request means the server couldn't understand the request: the syntax is broken, so it can't even be parsed. 422 Unprocessable Content means the request was well formed and understood, but the data fails validation. Malformed JSON is a 400. Valid JSON with an invalid email address is a 422.

400 Bad Request422 Unprocessable Content
MeaningI can't parse thisI parsed it, and it's invalid
ExamplesMalformed JSON, wrong Content-Type, oversized or broken header, missing required query parameterInvalid email, unknown enum value, end date before start date, quantity below zero
Defined inRFC 9110RFC 9110 (originally WebDAV, RFC 4918, as "Unprocessable Entity")
Common inEvery server and proxyRails, Laravel, FastAPI, the GitHub API
HTTP/1.1 400 Bad Request
Content-Type: application/json

{"error": "invalid_json", "message": "Unexpected token } in JSON at position 41"}
HTTP/1.1 422 Unprocessable Content
Content-Type: application/json

{"error": "validation_failed", "fields": {"email": "is not a valid email address"}}

Common causes of 400

  • Malformed body. A trailing comma, single quotes, or a body that was truncated.
  • Content type mismatch. Sending JSON without Content-Type: application/json, or form data to an endpoint expecting JSON.
  • Bad headers or cookies. nginx returns 400 Bad Request: Request Header Or Cookie Too Large when headers exceed large_client_header_buffers. Clearing the site's cookies fixes it for visitors.
  • Invalid URL. Unencoded characters in the path or query string.
  • Plain HTTP to an HTTPS port. nginx answers 400 The plain HTTP request was sent to HTTPS port.

Common causes of 422

  • Field validation. A required field is empty, a string is too long, a format doesn't match.
  • Business rules. A coupon that has expired, a duplicate username (some APIs use 409 for this), an invalid state transition.
  • Framework defaults. FastAPI returns 422 for any request that fails its Pydantic model. Rails scaffold controllers return 422 when a record fails to save.

How to fix them

As a visitor: for a persistent 400 on one site, clear that site's cookies. Otherwise check the URL for typos.

As a developer calling an API: read the response body. Good APIs say exactly which field failed. Then:

  1. Log the exact request you sent, not the object you meant to send. curl -v or your HTTP client's debug mode.
  2. Validate the JSON (jq . payload.json).
  3. Check Content-Type and encoding.
  4. Compare against the API's schema, including types: "5" and 5 are different.

400 and 422 on a webhook endpoint

A webhook handler returning 400 or 422 almost always means the payload isn't the shape the code expected. A provider added a field, sent a different event type, used form encoding, or set a field to null. Retrying won't help, because the same payload will fail the same way.

Debug it by looking at the raw request rather than guessing. Point the provider (or a copy of its traffic) at a free Webhook Bin URL and you'll see the exact method, headers and body. If the problem is that your destination expects a different format, such as forwarding one provider's event into another service's API, a Webhook Relay transform function can rename fields, restructure the JSON or drop events before delivery.

Two rules for webhook handlers:

  • Accept unknown fields and event types. Ignore what you don't need instead of failing validation on it, and acknowledge unhandled event types with 200.
  • Don't validate before you verify. Check the signature on the raw body first, then parse and validate.

When to return 400 vs 422 from your own API

Pick a convention and keep to it. A clear one: 400 for anything your parser or router rejects, 422 for well-formed requests that fail field or business validation. Always return a machine-readable body naming the failing fields. Never return 500 for bad input; that's a bug in your validation.

Frequently asked questions

What is the difference between 400 and 422?

400 Bad Request means the server couldn't understand the request at all: malformed JSON, a wrong Content-Type, a broken header or a missing required parameter. 422 Unprocessable Content means the request was well formed and the server understood it, but the content fails validation, such as an invalid email address or an end date before the start date.

What does HTTP 422 mean?

HTTP 422 Unprocessable Content, formerly called Unprocessable Entity, means the server understood the content type and the syntax was correct, but it couldn't process the instructions because the data is semantically invalid. It is the usual response for validation errors in Rails, Laravel, FastAPI and the GitHub API.

Should I use 400 or 422 for validation errors?

Both are acceptable, and consistency matters more than the choice. A common convention is 400 for anything the parser rejects and 422 for well-formed requests that fail business or field validation. Whichever you pick, return a body listing which fields failed and why.

Why does my webhook endpoint return 400?

Usually the body isn't what your handler expected. The provider sent form-encoded data and you expected JSON, the event type has a different shape, a field is null, or your framework's body parser rejected the content type. Capture the raw request to see exactly what arrived.

Will a webhook provider retry a 400 or 422?

It depends on the provider. Some retry every non-2xx response, others treat 4xx as permanent and stop. Since the same payload will fail the same way, a 4xx retry rarely helps; fix the handler and replay the event instead.