API Error Handling Guidelines
Table of Contents
- Error Response Format
- HTTP Status Codes
- Error Types
- Validation Errors
- Authentication & Authorization
- Rate Limiting
- Error Logging
- Client-Side Handling
Error Response Format
Standard Error Response
{
"error": {
"code": "INVALID_INPUT",
"message": "One or more validation errors occurred.",
"target": "user_registration",
"details": [
{
"code": "REQUIRED_FIELD",
"target": "email",
"message": "Email is required"
},
{
"code": "INVALID_FORMAT",
"target": "password",
"message": "Password must be at least 8 characters"
}
],
"innerError": {
"code": "VALIDATION_ERROR",
"requestId": "a1b2c3d4",
"timestamp": "2025-06-30T06:27:45Z"
}
}
}
HTTP Status Codes
2xx Success
200 OK
: Standard success response201 Created
: Resource created successfully202 Accepted
: Request accepted for processing204 No Content
: Success with no content to return
4xx Client Errors
400 Bad Request
: Invalid request format401 Unauthorized
: Authentication required403 Forbidden
: Insufficient permissions404 Not Found
: Resource doesn't exist405 Method Not Allowed
: HTTP method not supported406 Not Acceptable
: Requested format not available409 Conflict
: Resource conflict410 Gone
: Resource permanently removed422 Unprocessable Entity
: Validation errors429 Too Many Requests
: Rate limit exceeded
5xx Server Errors
500 Internal Server Error
: Generic server error501 Not Implemented
: Feature not implemented502 Bad Gateway
: Invalid response from upstream503 Service Unavailable
: Service temporarily unavailable504 Gateway Timeout
: Upstream timeout
Error Types
Standard Error Codes
Code | Description |
---|---|
AUTH_REQUIRED |
Authentication required |
FORBIDDEN |
Insufficient permissions |
INVALID_INPUT |
Invalid request data |
NOT_FOUND |
Resource not found |
RATE_LIMIT_EXCEEDED |
Too many requests |
RESOURCE_EXISTS |
Resource already exists |
SERVICE_ERROR |
Internal server error |
VALIDATION_ERROR |
Data validation failed |
Validation Errors
Request Validation
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"code": "REQUIRED",
"target": "email",
"message": "Email is required"
},
{
"code": "INVALID_FORMAT",
"target": "email",
"message": "Invalid email format"
},
{
"code": "MIN_LENGTH",
"target": "password",
"message": "Password must be at least 8 characters",
"constraints": {
"min": 8
}
}
]
}
}
Business Rule Validation
{
"error": {
"code": "BUSINESS_RULE_VIOLATION",
"message": "Cannot delete active user",
"details": [
{
"code": "USER_ACTIVE",
"target": "user",
"message": "Cannot delete user with active subscriptions"
}
]
}
}
Authentication and Authorization
Authentication Error
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or expired authentication token",
"details": [
{
"code": "TOKEN_EXPIRED",
"target": "authorization",
"message": "Token expired at 2025-06-30T12:00:00Z"
}
]
}
}
Authorization Error
{
"error": {
"code": "FORBIDDEN",
"message": "Insufficient permissions",
"details": [
{
"code": "MISSING_PERMISSION",
"target": "user:delete",
"message": "Requires 'admin' role"
}
]
}
}
Rate Limiting
Rate Limit Response Headers
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1625040000
Retry-After: 60
Rate Limit Error
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests, please try again later",
"details": [
{
"code": "RATE_LIMIT_REACHED",
"target": "api",
"message": "Rate limit of 100 requests per hour exceeded"
}
],
"retryAfter": 60
}
}
Error Logging
Log Entry Example
{
"timestamp": "2025-06-30T06:27:45.123Z",
"level": "ERROR",
"requestId": "a1b2c3d4",
"correlationId": "x-correlation-id-value",
"method": "POST",
"path": "/api/users",
"status": 400,
"durationMs": 42,
"userAgent": "Mozilla/5.0",
"clientIp": "192.168.1.1",
"error": {
"name": "ValidationError",
"message": "Validation failed",
"code": "VALIDATION_ERROR",
"details": [
{
"code": "REQUIRED",
"target": "email",
"message": "Email is required"
}
],
"stack": "ValidationError: Validation failed..."
},
"environment": "production",
"version": "1.0.0"
}
Client-Side Handling
Error Handling Best Practices
- User-Friendly Messages: Map error codes to user-friendly messages
- Retry Logic: Implement retry for transient errors (5xx, 429)
- Circuit Breaker: Prevent cascading failures
- Error Boundaries: Gracefully handle UI errors
- Error Reporting: Report client-side errors to monitoring
Example Error Boundary (React)
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
// Log error to error reporting service
logErrorToService(error, errorInfo);
}
render() {
if (this.state.hasError) {
return (
<div className="error-boundary">
<h2>Something went wrong</h2>
<p>{this.state.error?.message}</p>
<button onClick={() => window.location.reload()}>
Reload Page
</button>
</div>
);
}
return this.props.children;
}
}
Client Error Handling (JavaScript)
```javascript async function fetchWithErrorHandling(url, options = {}) { try { const response = await fetch(url, { ...options, headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', ...options.headers, }, });
const data = await response.json();
if (!response.ok) {
// Handle API errors
const error = new Error(data.error?.message || 'API request failed');
error.code = data.error?.code || 'API_ERROR';
error.status = response.status;
error.details = data.error?.details || [];
throw error;
}
return data;
} catch (error) { if (error.name === 'AbortError') { console.log('Request was aborted'); throw new Error('Request was cancelled'); }
// Handle network errors
if (!navigator.onLine) {
throw new Error('No internet connection');
}
// Re-throw the error for the caller to handle
throw error;
} }