API Error Handling
debt(d6/e5/b6/t5)
Closest to 'specialist tool catches it' (d5), +1. Tools like Spectral (OpenAPI linter) and Postman can catch some inconsistencies in error schemas, but detection_hints.automated is 'no' — much of the problem (inconsistent error formats across endpoints, missing machine-readable codes, HTML error pages leaking through) requires manual review or runtime testing. A mix of specialist tooling and code review pushes this to d6.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix describes adopting RFC 7807 Problem Details format, which sounds like a single pattern — but common_mistakes reveal the real scope: every endpoint may return different error shapes, validation errors use wrong status codes, stack traces leak in production. Fixing this means touching error handling across all API endpoints, middleware, exception handlers, and potentially client code. It's a significant refactor within the API layer but not necessarily a full architectural rework, so e5.
Closest to 'persistent productivity tax' (b5), +1. Applies to all web/api contexts. Once error handling is inconsistent, every new endpoint risks perpetuating the problem, and every client integration must cope with multiple error shapes. The choice of error format is cross-cutting — it shapes middleware, exception handlers, client SDKs, and documentation. It's not quite 'defines the system's shape' (b9) but it has strong gravitational pull on API consumers and internal error handling patterns, landing at b6.
Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception — that error messages are only for humans — is widespread among developers building their first APIs. Many developers return 200 OK with an error message string, or return generic 500s for client input errors, not realizing clients need machine-readable codes and proper HTTP status codes. This is a well-documented gotcha (RFC 7807/9457 exists precisely for this), but developers coming from server-rendered web apps consistently get it wrong initially.
Also Known As
TL;DR
Explanation
RFC 7807 (Problem Details for HTTP APIs) defines a standard error format: type (URI identifying the error type), title (human-readable summary), status (HTTP status code), detail (human-readable explanation), and instance (URI of the specific occurrence). APIs should use consistent error shapes, appropriate 4xx/5xx codes, field-level validation errors for 422 responses, and never return 200 for errors. Error messages should help developers, not expose system internals.
Diagram
flowchart TD
ERROR[API Error] --> FORMAT{Response format}
FORMAT --> RFC7807[RFC 7807 Problem Details<br/>type title status detail]
subgraph HTTP Status
VAL[400 Bad Request<br/>validation failed]
AUTH[401 Unauthorized<br/>missing or bad token]
FORBID[403 Forbidden<br/>authenticated but no permission]
NF[404 Not Found<br/>resource doesnt exist]
CONF[409 Conflict<br/>state conflict]
UNPROC[422 Unprocessable<br/>semantic validation failed]
RATE[429 Too Many Requests<br/>Retry-After header]
SRV[500 Internal Error<br/>never expose stack trace]
end
RFC7807 --> VAL & AUTH & FORBID & NF & CONF & UNPROC & RATE & SRV
style SUCCESS2 fill:#238636,color:#fff
style SRV fill:#f85149,color:#fff
style VAL fill:#d29922,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Returning 500 for validation errors — 422 Unprocessable Entity is correct for bad client input.
- Stack traces in production error responses — leaks internal structure and file paths.
- Different error shapes from different endpoints — clients cannot write reusable error handling code.
- No machine-readable error code — clients must parse error message strings to identify the error type.
Avoid When
- Returning 200 OK with an error in the body — HTTP status codes communicate error type to clients and proxies.
- Exposing stack traces or internal error details in production responses — they reveal implementation details to attackers.
- Using 500 for all errors — use specific codes: 400 bad input, 401 unauthenticated, 403 forbidden, 404 not found, 422 validation.
- Returning different error shapes from different endpoints — clients must handle one schema, not many.
When To Use
- Always return a consistent error envelope: code, message, and optionally a details array.
- Use RFC 9457 (Problem Details for HTTP APIs) for standardised, machine-readable error responses.
- Include a request ID in every error response so clients can correlate with server logs.
- Return validation errors as a structured list so clients can highlight individual fields.
Code Examples
// 200 with error, no structure, leaks internals:
HTTP/1.1 200 OK
{"error": true, "msg": "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'alice@example.com'"}
// Leaks DB structure, returns 200 = success to monitoring
// RFC 7807 Problem Details:
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json
{
"type": "https://api.example.com/errors/validation",
"title": "Validation Failed",
"status": 422,
"detail": "The request data failed validation",
"errors": [
{"field": "email", "code": "duplicate", "message": "Email already in use"}
]
}