Overview
The API uses a standardized error handling system that returns consistent error responses across all endpoints. All errors include a success: false flag and a descriptive error message.
All error responses follow this structure:
{
"success": false,
"error": "Error message describing what went wrong"
}
HTTP Status Codes
The API uses standard HTTP status codes to indicate the type of error:
| Status Code | Meaning | Common Causes |
|---|
400 | Bad Request | Invalid input data, validation errors, malformed requests |
401 | Unauthorized | Missing or invalid authentication token |
403 | Forbidden | Insufficient permissions (e.g., trying to edit someone else’s review) |
404 | Not Found | Resource doesn’t exist, invalid route |
409 | Conflict | Duplicate resource (e.g., reviewing the same route twice) |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Unexpected server error |
Error Types
1. Custom Application Errors
The API defines custom error classes for specific scenarios:
// 401 Unauthorized
{
"success": false,
"error": "No authentication token provided"
}
// 403 Forbidden
{
"success": false,
"error": "You don't have permission to edit this review"
}
// 404 Not Found
{
"success": false,
"error": "Route not found"
}
// 409 Conflict
{
"success": false,
"error": "You have already reviewed this route"
}
Location: /home/daytona/workspace/source/src/shared/middlewares/error.middleware.ts:18
2. Validation Errors (Zod)
When request data fails validation, the API returns detailed field-level errors:
{
"success": false,
"error": "Validation Error",
"details": [
{
"field": "rating",
"message": "Rating must be between 1 and 5"
},
{
"field": "comment",
"message": "Comment must be at least 10 characters"
}
]
}
Status Code: 400 Bad Request
Location: /home/daytona/workspace/source/src/shared/middlewares/error.middleware.ts:27
3. Database Errors (Prisma)
The API handles common database errors gracefully:
Unique Constraint Violation (P2002)
{
"success": false,
"error": "A record with this value already exists",
"field": ["email"]
}
Status Code: 409 Conflict
Location: /home/daytona/workspace/source/src/shared/middlewares/error.middleware.ts:41
Record Not Found (P2025)
{
"success": false,
"error": "Record not found"
}
Status Code: 404 Not Found
Location: /home/daytona/workspace/source/src/shared/middlewares/error.middleware.ts:50
Foreign Key Constraint (P2003)
{
"success": false,
"error": "Invalid reference to related record",
"field": "userId"
}
Status Code: 400 Bad Request
Location: /home/daytona/workspace/source/src/shared/middlewares/error.middleware.ts:58
{
"success": false,
"error": "Invalid data format"
}
Status Code: 400 Bad Request
Location: /home/daytona/workspace/source/src/shared/middlewares/error.middleware.ts:68
4. Route Not Found (404)
When accessing a non-existent endpoint:
{
"success": false,
"error": "Route not found",
"path": "/api/invalid-endpoint"
}
Status Code: 404 Not Found
Location: /home/daytona/workspace/source/src/shared/middlewares/error.middleware.ts:91
5. Internal Server Error (500)
For unexpected errors, the API returns a generic error message:
{
"success": false,
"error": "Internal Server Error"
}
In development mode, additional debug information is included:
{
"success": false,
"error": "Internal Server Error",
"details": "Detailed error message",
"stack": "Error stack trace..."
}
Status Code: 500 Internal Server Error
Location: /home/daytona/workspace/source/src/shared/middlewares/error.middleware.ts:76
Stack traces and detailed error messages are only included in development mode for security reasons.
Error Handling Examples
JavaScript/TypeScript
try {
const response = await fetch('/api/routes/ruta-1/reviews', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
rating: 5,
comment: 'Great route!'
})
});
const data = await response.json();
if (!data.success) {
// Handle error
if (response.status === 409) {
console.error('You already reviewed this route');
} else if (response.status === 401) {
console.error('Please log in to review');
} else {
console.error(data.error);
}
return;
}
// Success
console.log('Review created:', data.data);
} catch (error) {
console.error('Network error:', error);
}
Handling Validation Errors
const response = await fetch('/api/routes/ruta-1/reviews', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ rating: 6 }) // Invalid rating
});
const data = await response.json();
if (response.status === 400 && data.details) {
// Show field-specific errors
data.details.forEach(error => {
console.error(`${error.field}: ${error.message}`);
// Display error next to the form field
});
}
Best Practices
- Always check the
success field in responses to determine if the request succeeded
- Use HTTP status codes to determine the appropriate error handling strategy
- Display validation errors next to the relevant form fields for better UX
- Handle authentication errors by redirecting to login or refreshing tokens
- Log unexpected 500 errors and provide a user-friendly message
- Don’t expose sensitive information in production error messages