Error Handling
Understanding and handling API errors effectively.
Error Response Format
All API errors follow a consistent format:
json
{
"success": false,
"error": "Error message description",
"code": "ERROR_CODE",
"details": {
"field": "Additional context"
}
}HTTP Status Codes
2xx Success
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource created successfully |
| 204 | No Content | Request succeeded, no content returned |
4xx Client Errors
| Code | Status | Description |
|---|---|---|
| 400 | Bad Request | Invalid request parameters or body |
| 401 | Unauthorized | Missing or invalid authentication token |
| 403 | Forbidden | Insufficient permissions for this action |
| 404 | Not Found | Resource not found |
| 405 | Method Not Allowed | HTTP method not supported for this endpoint |
| 409 | Conflict | Resource conflict (e.g., duplicate entry) |
| 422 | Unprocessable Entity | Request valid but unable to process |
| 429 | Too Many Requests | Rate limit exceeded |
5xx Server Errors
| Code | Status | Description |
|---|---|---|
| 500 | Internal Server Error | Unexpected server error |
| 502 | Bad Gateway | Server received invalid response |
| 503 | Service Unavailable | Service temporarily unavailable |
| 504 | Gateway Timeout | Server timeout |
Common Error Codes
Authentication Errors
json
{
"success": false,
"error": "Invalid or expired token",
"code": "AUTH_TOKEN_INVALID"
}Causes:
- Token expired
- Invalid token signature
- Token revoked
Solution: Re-authenticate with /api/auth/login
Authorization Errors
json
{
"success": false,
"error": "Admin privileges required",
"code": "AUTH_INSUFFICIENT_PERMISSIONS"
}Causes:
- User not admin
- Attempting admin-only operation
Solution: Contact server administrator
Validation Errors
json
{
"success": false,
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"details": {
"username": "Username is required",
"password": "Password must be at least 6 characters"
}
}Causes:
- Missing required fields
- Invalid field format
- Field constraints not met
Solution: Correct input and retry
Resource Not Found
json
{
"success": false,
"error": "Player not found",
"code": "PLAYER_NOT_FOUND"
}Causes:
- Player offline
- Invalid username
- Player doesn't exist
Solution: Verify player exists and is online
Rate Limiting
json
{
"success": false,
"error": "Too many requests",
"code": "RATE_LIMIT_EXCEEDED",
"details": {
"retryAfter": 60
}
}Causes:
- Too many requests in short time
Solution: Wait and retry after retryAfter seconds
Error Handling Examples
TypeScript
typescript
class APIError extends Error {
constructor(
public statusCode: number,
public code: string,
public details?: any
) {
super(`API Error ${statusCode}: ${code}`);
}
}
async function handleAPICall<T>(
request: () => Promise<Response>
): Promise<T> {
try {
const response = await request();
const data = await response.json();
if (!response.ok) {
throw new APIError(
response.status,
data.code || 'UNKNOWN_ERROR',
data.details
);
}
return data;
} catch (error) {
if (error instanceof APIError) {
// Handle specific error codes
switch (error.code) {
case 'AUTH_TOKEN_INVALID':
// Redirect to login
window.location.href = '/login';
break;
case 'RATE_LIMIT_EXCEEDED':
// Wait and retry
await new Promise(resolve =>
setTimeout(resolve, error.details?.retryAfter * 1000 || 60000)
);
return handleAPICall(request);
default:
console.error('API Error:', error);
}
}
throw error;
}
}
// Usage
try {
const data = await handleAPICall(() =>
fetch('http://localhost:8080/api/players', {
headers: { 'Authorization': `Bearer ${token}` }
})
);
console.log('Players:', data);
} catch (error) {
console.error('Failed to fetch players:', error);
}Python
python
class APIError(Exception):
def __init__(self, status_code, code, details=None):
self.status_code = status_code
self.code = code
self.details = details
super().__init__(f"API Error {status_code}: {code}")
def handle_api_call(request_func):
"""Handle API calls with error handling"""
try:
response = request_func()
if not response.ok:
data = response.json()
raise APIError(
response.status_code,
data.get('code', 'UNKNOWN_ERROR'),
data.get('details')
)
return response.json()
except APIError as e:
if e.code == 'AUTH_TOKEN_INVALID':
# Re-authenticate
print("Token expired, please login again")
elif e.code == 'RATE_LIMIT_EXCEEDED':
# Wait and retry
retry_after = e.details.get('retryAfter', 60)
print(f"Rate limited, waiting {retry_after}s")
time.sleep(retry_after)
return handle_api_call(request_func)
else:
print(f"API Error: {e}")
raise
# Usage
try:
data = handle_api_call(lambda: requests.get(
'http://localhost:8080/api/players',
headers={'Authorization': f'Bearer {token}'}
))
print('Players:', data)
except APIError as e:
print(f"Failed to fetch players: {e}")Retry Logic
typescript
async function retryWithBackoff<T>(
fn: () => Promise<T>,
maxRetries = 3,
baseDelay = 1000
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
// Exponential backoff
const delay = baseDelay * Math.pow(2, i);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw new Error('Max retries exceeded');
}
// Usage
const data = await retryWithBackoff(
() => fetchPlayers(token),
3, // max 3 retries
1000 // 1 second base delay
);Best Practices
1. Always Check Response Status
typescript
const response = await fetch(url);
if (!response.ok) {
const error = await response.json();
throw new Error(error.message);
}2. Handle Token Expiration
typescript
if (error.code === 'AUTH_TOKEN_INVALID') {
// Refresh token or redirect to login
await refreshToken();
// Retry original request
}3. Implement Exponential Backoff
For transient errors (5xx), use exponential backoff:
- 1st retry: wait 1s
- 2nd retry: wait 2s
- 3rd retry: wait 4s
4. Log Errors Appropriately
typescript
console.error('API Error:', {
endpoint: url,
status: error.statusCode,
code: error.code,
details: error.details,
timestamp: new Date().toISOString()
});5. User-Friendly Messages
typescript
function getUserMessage(errorCode: string): string {
const messages = {
'AUTH_TOKEN_INVALID': 'Your session has expired. Please login again.',
'AUTH_INSUFFICIENT_PERMISSIONS': 'You do not have permission for this action.',
'PLAYER_NOT_FOUND': 'Player not found. Please check the username.',
'RATE_LIMIT_EXCEEDED': 'Too many requests. Please wait a moment.',
};
return messages[errorCode] || 'An unexpected error occurred. Please try again.';
}Debugging Tips
Enable Debug Logging
typescript
const DEBUG = process.env.NODE_ENV === 'development';
if (DEBUG) {
console.log('API Request:', {
url,
method,
headers,
body
});
}Network Tab
Use browser DevTools Network tab to inspect:
- Request/response headers
- Response body
- Timing information
- HTTP status codes
API Testing Tools
- Postman: Test endpoints interactively
- Insomnia: REST client with GraphQL support
- cURL: Command-line testing
- HTTPie: User-friendly HTTP client
Related
- Getting Started - API setup
- Authentication - Auth errors
- Rate Limiting - Rate limit details