Error Handling Template
Document Control​
- Last Updated: February 4, 2025
- Version: 1.0.0
- Status: Active
- Owner: Development Team
- Next Review: May 4, 2025
Error Response Format​
Standard Error Response​
{
"status": "error",
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": {
"field1": "Error details for field1",
"field2": "Error details for field2"
},
"timestamp": "ISO-8601 timestamp",
"requestId": "Unique request identifier"
}
Error Categories​
4xx Client Errors​
400 Bad Request​
- Code: INVALID_REQUEST
- Description: The request was malformed or contains invalid parameters
- Example:
{
"status": "error",
"code": "INVALID_REQUEST",
"message": "Invalid request parameters",
"details": {
"email": "Must be a valid email address",
"age": "Must be a positive number"
}
}
401 Unauthorized​
- Code: UNAUTHORIZED
- Description: Authentication is required or provided credentials are invalid
- Example:
{
"status": "error",
"code": "UNAUTHORIZED",
"message": "Invalid or expired authentication token"
}
403 Forbidden​
- Code: FORBIDDEN
- Description: The authenticated user lacks required permissions
- Example:
{
"status": "error",
"code": "FORBIDDEN",
"message": "Insufficient permissions to access this resource"
}
404 Not Found​
- Code: NOT_FOUND
- Description: The requested resource does not exist
- Example:
{
"status": "error",
"code": "NOT_FOUND",
"message": "Resource with ID '123' not found"
}
5xx Server Errors​
500 Internal Server Error​
- Code: INTERNAL_ERROR
- Description: An unexpected error occurred on the server
- Example:
{
"status": "error",
"code": "INTERNAL_ERROR",
"message": "An unexpected error occurred",
"requestId": "req_123abc"
}
503 Service Unavailable​
- Code: SERVICE_UNAVAILABLE
- Description: The service is temporarily unavailable
- Example:
{
"status": "error",
"code": "SERVICE_UNAVAILABLE",
"message": "Service is undergoing maintenance"
}
Error Handling Guidelines​
Client-Side Error Handling​
try {
const response = await api.getData();
// Handle success
} catch (error) {
if (error.code === 'UNAUTHORIZED') {
// Handle authentication error
redirectToLogin();
} else if (error.code === 'NOT_FOUND') {
// Handle not found error
showNotFoundMessage();
} else {
// Handle other errors
showErrorMessage(error.message);
}
}
Server-Side Error Handling​
try {
const data = await processRequest();
return successResponse(data);
} catch (error) {
if (error instanceof ValidationError) {
return errorResponse({
status: 400,
code: 'INVALID_REQUEST',
message: 'Validation failed',
details: error.details
});
}
// Log unexpected errors
logger.error('Unexpected error', {
error,
requestId: context.requestId
});
return errorResponse({
status: 500,
code: 'INTERNAL_ERROR',
message: 'An unexpected error occurred',
requestId: context.requestId
});
}
Error Logging​
Required Information​
- Error code
- Stack trace
- Request context
- User context
- System state
- Timestamp
Log Format​
{
"level": "error",
"timestamp": "2025-02-04T06:28:28+05:30",
"requestId": "req-123",
"userId": "user-456",
"error": {
"code": "AUTH_ERROR",
"message": "Invalid token provided",
"stack": "...",
"details": {}
},
"context": {
"service": "auth-service",
"operation": "verify-token",
"environment": "production"
}
}
Error Recovery​
Retry Strategy​
const retryOperation = async (
operation: () => Promise<any>,
maxRetries: number = 3,
delay: number = 1000
): Promise<any> => {
let lastError: Error;
for (let i = 0; i < maxRetries; i++) {
try {
return await operation();
} catch (error) {
lastError = error;
await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i)));
}
}
throw lastError;
};
Circuit Breaker​
class CircuitBreaker {
private failures: number = 0;
private lastFailure: number = 0;
private readonly threshold: number = 5;
private readonly resetTimeout: number = 60000;
async execute(operation: () => Promise<any>): Promise<any> {
if (this.isOpen()) {
throw new Error('Circuit breaker is open');
}
try {
const result = await operation();
this.reset();
return result;
} catch (error) {
this.recordFailure();
throw error;
}
}
private isOpen(): boolean {
if (this.failures >= this.threshold) {
const now = Date.now();
if (now - this.lastFailure >= this.resetTimeout) {
this.reset();
return false;
}
return true;
}
return false;
}
private recordFailure(): void {
this.failures++;
this.lastFailure = Date.now();
}
private reset(): void {
this.failures = 0;
this.lastFailure = 0;
}
}
Related Documents​
- API Documentation Template
- Logging Standards
- Monitoring Guide
- Incident Response Plan
Usage Guide​
When to Use​
- Implementing new API endpoints
- Adding error handling to existing code
- Documenting error responses
- Creating client-side error handlers
Best Practices​
-
Error Response Format
- Use consistent structure
- Include error codes
- Provide clear messages
- Add helpful details
-
Error Codes
- Use descriptive codes
- Group by category
- Be consistent
- Document all codes
-
Error Messages
- Use clear language
- Be specific
- Include actionable info
- Avoid technical jargon
-
Security
- Hide sensitive details
- Log appropriately
- Sanitize output
- Handle all cases
Example​
# Authentication Error Handling
## Error Response Format
### Invalid Credentials
```json
{
"status": "error",
"code": "INVALID_CREDENTIALS",
"message": "The provided email or password is incorrect",
"timestamp": "2024-02-04T12:00:00Z",
"requestId": "auth_123abc"
}
Account Locked​
{
"status": "error",
"code": "ACCOUNT_LOCKED",
"message": "Account has been locked due to multiple failed attempts",
"details": {
"remainingTime": "30 minutes",
"attempts": 5,
"maxAttempts": 5
},
"timestamp": "2024-02-04T12:00:00Z",
"requestId": "auth_456def"
}
Error Handling Code​
Client-Side​
async function handleLogin(credentials: LoginCredentials) {
try {
const response = await authApi.login(credentials);
return response.data;
} catch (error) {
switch (error.code) {
case 'INVALID_CREDENTIALS':
showError('Invalid email or password');
break;
case 'ACCOUNT_LOCKED':
showError(`Account locked. Try again in ${error.details.remainingTime}`);
break;
default:
showError('An unexpected error occurred');
}
throw error;
}
}
Server-Side​
async function handleLoginRequest(req: Request, res: Response) {
try {
const { email, password } = req.body;
// Validate input
if (!email || !password) {
return res.status(400).json({
status: 'error',
code: 'INVALID_REQUEST',
message: 'Email and password are required'
});
}
// Check login attempts
if (await isAccountLocked(email)) {
return res.status(403).json({
status: 'error',
code: 'ACCOUNT_LOCKED',
message: 'Account is locked',
details: await getLockoutDetails(email)
});
}
// Attempt login
const user = await authenticateUser(email, password);
if (!user) {
await incrementFailedAttempts(email);
return res.status(401).json({
status: 'error',
code: 'INVALID_CREDENTIALS',
message: 'Invalid email or password'
});
}
// Success
await resetFailedAttempts(email);
return res.json({
status: 'success',
data: {
token: generateToken(user),
user: sanitizeUser(user)
}
});
} catch (error) {
logger.error('Login error', { error, email });
return res.status(500).json({
status: 'error',
code: 'INTERNAL_ERROR',
message: 'An unexpected error occurred'
});
}
}