17 Error Responses
title: Error Responses in REST API Design — Complete Guide weight: 27 date: 2026-06-28 lastmod: 2026-06-28 description: Design consistent REST API error responses with structured JSON envelopes, meaningful error codes, validation details, and proper HTTP status code mapping. tags: [api-development, rest]
Consistent error responses in REST APIs use a structured JSON envelope with error code, message, details, and trace ID, helping clients handle failures programmatically without parsing error text.
```mermaid
flowchart TD
A[Request] --> B{Validation}
B -->|Invalid| C[400 Bad Request]
B -->|Valid| D{Process}
D -->|Success| E[200 OK]
D -->|Server Error| F[500 Error]
C --> G[Error Envelope]
F --> G
G --> H[code, message, details, trace_id]
style A fill:#e1f5fe
style G fill:#ffcdd2
style H fill:#fff9c4
A good error response includes a unique error code for programmatic handling, a human-readable message, validation details showing which field failed and why, and a trace ID for debugging. The HTTP status code reflects the error category.
Think of error responses like an airplane's check engine light. The light (status code) tells you something is wrong. The diagnostic code (error code) tells you exactly which system failed. The mechanic's notes (message) explain what happened in human terms.
Example: Standard Error Envelope
import requests
response = requests.post(
"https://api.example.com/users",
json={"email": "not-an-email"}
)
error = response.json()
print(f"Status: {response.status_code}")
print(f"Code: {error['error']['code']}")
print(f"Message: {error['error']['message']}")
print(f"Trace ID: {error['error']['trace_id']}")
Expected output:
Status: 400
Code: VALIDATION_ERROR
Message: The request contains invalid fields
Trace ID: 550e8400-e29b-41d4-a716-446655440000
Example: Validation Error with Field Details
import requests
response = requests.post(
"https://api.example.com/users",
json={
"name": "",
"email": "invalid",
"age": -1
}
)
error = response.json()
print(f"Status: {response.status_code}")
for detail in error['error']['details']:
print(f" {detail['field']}: {detail['issue']}")
Expected output:
Status: 422
name: must not be empty
email: must be a valid email address
age: must be a positive integer
Example: Consistent Error Handling
import requests
def safe_api_call(url, method="GET", **kwargs):
try:
response = requests.request(method, url, **kwargs)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
error = e.response.json().get("error", {})
return {
"error": True,
"status": e.response.status_code,
"code": error.get("code", "UNKNOWN"),
"message": error.get("message", str(e)),
"details": error.get("details", [])
}
result = safe_api_call(
"https://api.example.com/users/99999"
)
if result.get("error"):
print(f"[{result['code']}] {result['message']}")
else:
print(result)
Expected output:
[NOT_FOUND] User with id 99999 was not found
Common Mistakes
- Returning unstructured error messages — Returning just "Invalid input" without details forces clients to implement fragile string parsing.
- Exposing stack traces — Returning a 500 error with a Python traceback or SQL query exposes internal implementation details and security vulnerabilities.
- Inconsistent error structure across endpoints — If
/usersreturns{"error": "..."}but/ordersreturns{"message": "..."}, clients cannot use a generic error handler. - Using 200 OK with an error flag in the body — This breaks HTTP semantics. Use the appropriate 4xx or 5xx status code.
- Not including a correlation ID — Without a trace ID, clients and support teams cannot correlate errors with server logs for debugging.
Practice Questions
- What fields should a consistent error envelope include?
- Why should you return error details for validation failures?
- What status code should you use for a malformed request body?
- Why is it dangerous to expose stack traces in error responses?
- Challenge: Design an error response system for a payment API that handles insufficient funds, declined cards, expired cards, invalid CVV, and duplicate transactions. Each error should have a unique code and actionable message.
FAQ
Mini Project
Build a Python error-handling utility class that generates consistent error responses. Support validation errors with field details, authentication errors, not-found errors, and server errors. Each response should include a trace ID, error code, message, and optional details.
What's Next
Now learn about authentication design in REST API Design.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro