Skip to main content

Error Handling

This guide covers the error format, common error codes, and best practices for handling errors in your applications.

Error Format

All errors follow a consistent JSON structure:

{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": {
// Additional context (optional)
},
"request_id": "req_abc123xyz"
}
}
FieldDescription
codeMachine-readable error code
messageHuman-readable description
detailsAdditional context (field errors, limits, etc.)
request_idUnique identifier for support requests

HTTP Status Codes

StatusMeaningWhen It Occurs
400Bad RequestInvalid request syntax or parameters
401UnauthorizedMissing or invalid authentication
403ForbiddenValid auth but insufficient permissions
404Not FoundResource doesn't exist
409ConflictResource state conflict
422Unprocessable EntityValidation errors
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer-side error
502Bad GatewayUpstream service error
503Service UnavailableTemporary maintenance
504Gateway TimeoutRequest timeout

Common Error Codes

Authentication Errors (401)

{
"error": {
"code": "INVALID_TOKEN",
"message": "The provided access token is invalid or expired"
}
}
CodeDescription
INVALID_TOKENToken is malformed or expired
TOKEN_EXPIREDToken has expired
INVALID_API_KEYAPI key is invalid
API_KEY_EXPIREDAPI key has expired
MISSING_AUTHNo authentication provided

Authorization Errors (403)

{
"error": {
"code": "INSUFFICIENT_PERMISSIONS",
"message": "You don't have permission to access this resource",
"details": {
"required": "write:schedules",
"granted": ["read:schedules"]
}
}
}
CodeDescription
INSUFFICIENT_PERMISSIONSMissing required permissions
RESOURCE_ACCESS_DENIEDCannot access this specific resource
IP_NOT_ALLOWEDRequest from unauthorized IP
ACCOUNT_SUSPENDEDAccount has been suspended

Validation Errors (422)

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": {
"fields": {
"name": ["Site name is required"],
"location": ["Must be a valid location string"]
}
}
}
}
CodeDescription
VALIDATION_ERROROne or more fields failed validation
INVALID_FORMATRequest body format is invalid
MISSING_FIELDRequired field is missing
INVALID_VALUEField value is not acceptable

Resource Errors (404, 409)

{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "Asset not found",
"details": {
"resource_type": "Asset",
"resource_id": "ast_abc123"
}
}
}
CodeDescription
RESOURCE_NOT_FOUNDResource doesn't exist
ALREADY_EXISTSResource already exists
CONFLICTState conflict (e.g., concurrent modification)
GONEResource was deleted

Rate Limiting Errors (429)

{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests",
"details": {
"limit": 1000,
"window": 60,
"retry_after": 45
}
}
}

Server Errors (5xx)

{
"error": {
"code": "INTERNAL_ERROR",
"message": "An unexpected error occurred",
"request_id": "req_abc123xyz"
}
}
CodeDescription
INTERNAL_ERRORUnexpected server error
SERVICE_UNAVAILABLETemporary maintenance
UPSTREAM_ERRORDependency service failed
TIMEOUTRequest processing timeout

Error Handling Best Practices

1. Always Check Status Codes

import requests

def handle_api_request(method, url, **kwargs):
response = requests.request(method, url, **kwargs)

if response.ok:
return response.json()

error_data = response.json().get('error', {})

if response.status_code == 401:
raise AuthenticationError(error_data['message'])
elif response.status_code == 403:
raise PermissionError(error_data['message'])
elif response.status_code == 404:
raise NotFoundError(error_data['message'])
elif response.status_code == 422:
raise ValidationError(error_data['details'])
elif response.status_code == 429:
raise RateLimitError(
error_data['message'],
retry_after=error_data['details']['retry_after']
)
elif response.status_code >= 500:
raise ServerError(
error_data['message'],
request_id=error_data.get('request_id')
)
else:
raise APIError(error_data['message'])

2. Handle Validation Errors Gracefully

Display field-specific errors to users:

async function createSite(siteData) {
try {
return await api.createSite(siteData);
} catch (error) {
if (error.code === 'VALIDATION_ERROR') {
// Map errors to form fields
const fieldErrors = error.details.fields;

Object.entries(fieldErrors).forEach(([field, messages]) => {
showFieldError(field, messages.join(', '));
});

return null;
}
throw error;
}
}

3. Implement Retry Logic for Transient Errors

import time
from functools import wraps

def retry_on_error(max_retries=3, retry_on=(500, 502, 503, 504)):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
last_error = None

for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except APIError as e:
last_error = e

if e.status_code == 429:
time.sleep(e.retry_after)
elif e.status_code in retry_on:
delay = 2 ** attempt # Exponential backoff
time.sleep(delay)
else:
raise

raise last_error
return wrapper
return decorator

@retry_on_error(max_retries=3)
def fetch_site(site_id):
return api.get_site(site_id)

4. Log Request IDs for Debugging

import logging

logger = logging.getLogger(__name__)

try:
result = api.create_schedule(schedule_data)
except APIError as e:
logger.error(
f"API Error: {e.code} - {e.message}",
extra={
'request_id': e.request_id,
'error_details': e.details
}
)
# Include request_id in support tickets
raise UserFacingError(
f"Something went wrong. Reference: {e.request_id}"
)

5. Provide Helpful User Messages

Map technical errors to user-friendly messages:

const ERROR_MESSAGES = {
'INVALID_TOKEN': 'Your session has expired. Please log in again.',
'INSUFFICIENT_PERMISSIONS': 'You don\'t have access to this feature.',
'RESOURCE_NOT_FOUND': 'The requested item could not be found.',
'VALIDATION_ERROR': 'Please check your input and try again.',
'RATE_LIMIT_EXCEEDED': 'Too many requests. Please wait a moment.',
'INTERNAL_ERROR': 'Something went wrong. Please try again later.',
};

function getErrorMessage(error) {
return ERROR_MESSAGES[error.code] || 'An unexpected error occurred.';
}

Debugging Tips

Use Request ID for Support

When contacting support, always include:

  1. Request ID from the error response
  2. Timestamp of when the error occurred
  3. Endpoint you were calling
  4. Request body (sanitized of sensitive data)

Enable Debug Logging

# Include debug info in response
curl -X GET "https://platform.powerverse.com/inventory-service/assets" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Debug: true"

Response includes additional debugging info:

{
"data": [...],
"debug": {
"request_id": "req_abc123",
"duration_ms": 45,
"server": "api-prod-1"
}
}

Next Steps