Handling Error Responses

1. Configuring Standard Error Formats

FormatSpecification
RFC 7807Problem Details for HTTP APIs
JSON:API errorsjsonapi.org/format/#errors
Google API Error{ error: { code, message, status } }
GraphQL errorserrors[] in body

2. Setting Custom Error Messages

Example: Friendly error template

{
  "type": "https://errors.example.com/insufficient-funds",
  "title": "Insufficient Funds",
  "status": 402,
  "detail": "Account balance $5.00 is less than required $25.00",
  "instance": "/v1/payments/p_abc123",
  "balance": 5.00,
  "required": 25.00,
  "request_id": "req_xyz789"
}

3. Implementing Error Code Mapping

StatusMeaningRetry?
400Bad RequestNo (fix req)
401UnauthenticatedAfter re-auth
403ForbiddenNo
404Not FoundNo
409ConflictMaybe
422Unprocessable EntityNo
429Too Many RequestsYes (backoff)
500Server ErrorYes
502/503/504Gateway/UpstreamYes

4. Using Error Response Templates

Example: NGINX custom error pages

error_page 404 /errors/404.json;
error_page 502 503 504 /errors/upstream.json;
location ~ ^/errors/ { internal; root /etc/nginx; }

5. Configuring Detailed vs Generic Errors

EnvironmentDetail Level
ProductionGeneric message + request_id
StagingDetail + stack hash
DevelopmentFull stack trace
Admin/debug headerVerbose with auth
Warning: Never leak SQL, file paths, or stack traces to public clients — info disclosure (OWASP A05).

6. Setting Up Error Logging

FieldWhy
request_idCorrelate with client
trace_idLink to distributed trace
user_id / api_key_hashIdentify caller
route + methodLocate problem
upstream statusRoot cause
stack hashGroup identical errors

7. Using Problem Details (RFC 7807)

FieldRequiredDescription
typeYesURI identifying problem
titleYesShort summary
statusRecommendedHTTP code
detailOptionalSpecific to occurrence
instanceOptionalURI of this occurrence
ExtensionsOptionalCustom fields allowed

8. Implementing Error Retry Logic

Example: Exponential backoff with jitter

int attempt = 0;
while (attempt < maxRetries) {
  Response r = call();
  if (r.status < 500 && r.status != 429) return r;
  int baseMs = (int) Math.min(30000, 100 * Math.pow(2, attempt));
  int sleep = ThreadLocalRandom.current().nextInt(baseMs / 2, baseMs);
  Thread.sleep(sleep);
  attempt++;
}

9. Configuring Fallback Responses

Fallback SourceUse
Cached last-goodServe stale
Static JSONEmpty list, default
Secondary upstreamFailover
Degraded mode flagClient switches UX

10. Setting Error Response Headers

HeaderUse
Content-Type: application/problem+jsonRFC 7807 signal
Retry-After429/503 hint
X-Request-IDCorrelation
WWW-Authenticate401 challenge
Cache-Control: no-storeDon't cache errors