Validation Errors
Validation errors are the most common errors an API returns, and the ones clients most want to render nicely. A good validation response tells the user exactly which fields are wrong and why — all of them at once, not one per round trip.
Status: 422 (or 400)
Section titled “Status: 422 (or 400)”When the request parsed correctly but the values fail your rules, return 422 Unprocessable Entity. Some teams use 400 for all client errors; either is defensible, but be consistent. Reserve 400 for requests you could not even parse.
A field-level error body
Section titled “A field-level error body”Extend Problem Details with an errors array, one entry per offending field:
{ "type": "https://api.example.com/problems/validation", "title": "Validation failed", "status": 422, "detail": "The request has 2 invalid fields.", "errors": [ { "field": "email", "message": "must be a valid email address" }, { "field": "age", "message": "must be 18 or greater" } ]}Collect all errors, then respond
Section titled “Collect all errors, then respond”Validate every field and gather all failures before responding — do not bail on the first. This mirrors how a typical schema validator works:
In TypeScript projects a schema library (such as zod) gives you this for free: parse the input against a schema, and on failure map the issues to your errors array.
| Advantages (Validation Errors) | Trade-offs |
|---|---|
| Clients know which field is wrong and why — better UX | Validation logic ends up duplicated between client and server |
| Prevents invalid data from reaching the database | A verbose error response for forms with many fields |
| A clear 400/422 keeps retry logic correct | Some rules need a database query (e.g. email uniqueness) |
| Machine-readable errors let the client show inline messages |
Common mistakes
Section titled “Common mistakes”Returning one error at a time for multiple bad fields Symptom:
- A form has 5 invalid fields, but the API returns errors one field at a time
- The user fixes the first field, resubmits, sees the second error, fixes it, resubmits again…
- Validate every field at once and return the full
errorsarray in one response
Mixing validation errors with business rule errors Symptom:
400 Bad Requestused for both “invalid email format” and “this email is suspended”- The client can’t tell whether to show a field error or a general error
- Split them:
422for validation,409or a custom code for business rules
💡 Real-world examples
Stripe API:
{ "error": { "type": "invalid_request_error", "param": "amount", "message": "Amount must be greater than 0" } }paramnames the field at fault — the client shows an inline error thereGitHub API:
{ "errors": [{ "resource": "Issue", "field": "title", "code": "missing_field" }, { "resource": "Issue", "field": "body", "code": "missing_field" }] }- Returns validation errors for every field at once, not one at a time
Sources: Stripe API — errors, GitHub REST API errors