Error Handling
How the Ever Gauzy API handles errors and how to interpret error responses.
Error Response Formatโ
All error responses follow a consistent structure:
{
"statusCode": 400,
"message": "Error description",
"error": "Bad Request"
}
For validation errors, message may be an array:
{
"statusCode": 400,
"message": [
"firstName must be a string",
"firstName should not be empty",
"email must be an email"
],
"error": "Bad Request"
}
HTTP Status Codesโ
Client Errors (4xx)โ
| Code | Name | Description | Common Cause |
|---|---|---|---|
| 400 | Bad Request | Invalid request body or parameters | Validation failure, malformed JSON |
| 401 | Unauthorized | Authentication required or failed | Missing/invalid JWT token |
| 403 | Forbidden | Authenticated but not authorized | Insufficient role/permissions |
| 404 | Not Found | Resource does not exist | Wrong ID, deleted resource |
| 405 | Method Not Allowed | Wrong HTTP method | Using GET instead of POST |
| 409 | Conflict | Duplicate or conflicting resource | Unique constraint violation |
| 422 | Unprocessable Entity | Valid syntax but semantic error | Business logic violation |
| 429 | Too Many Requests | Rate limit exceeded | Too many API calls |
Server Errors (5xx)โ
| Code | Name | Description |
|---|---|---|
| 500 | Internal Server Error | Unexpected server error |
| 502 | Bad Gateway | Upstream service unavailable |
| 503 | Service Unavailable | Server overloaded or maintenance |
Common Error Scenariosโ
Authentication Errorsโ
Invalid credentials:
{
"statusCode": 401,
"message": "Incorrect email or password",
"error": "Unauthorized"
}
Expired token:
{
"statusCode": 401,
"message": "Token has expired",
"error": "Unauthorized"
}
Missing token:
{
"statusCode": 401,
"message": "Unauthorized"
}
Permission Errorsโ
Insufficient permissions:
{
"statusCode": 403,
"message": "You do not have permission to access this resource",
"error": "Forbidden"
}
Wrong tenant:
{
"statusCode": 403,
"message": "You do not have access to this tenant",
"error": "Forbidden"
}
Validation Errorsโ
Missing required field:
{
"statusCode": 400,
"message": ["name should not be empty", "name must be a string"],
"error": "Bad Request"
}
Invalid UUID:
{
"statusCode": 400,
"message": ["organizationId must be a UUID"],
"error": "Bad Request"
}
Not Found Errorsโ
Resource not found:
{
"statusCode": 404,
"message": "Record not found",
"error": "Not Found"
}
Conflict Errorsโ
Duplicate entry:
{
"statusCode": 409,
"message": "Email already exists",
"error": "Conflict"
}
Error Handling in NestJSโ
The backend uses NestJS built-in exception classes:
// 400
throw new BadRequestException("Invalid input");
// 401
throw new UnauthorizedException("Token expired");
// 403
throw new ForbiddenException("Insufficient permissions");
// 404
throw new NotFoundException("Employee not found");
// 409
throw new ConflictException("Email already exists");
Retry Strategyโ
For transient errors (5xx, network timeouts), implement exponential backoff:
async function apiCallWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.status >= 500)
throw new Error(`Server error: ${response.status}`);
return response;
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise((resolve) =>
setTimeout(resolve, Math.pow(2, i) * 1000),
);
}
}
}
When to Retryโ
| Error | Retry? | Notes |
|---|---|---|
400 Bad Request | โ | Fix the request |
401 Unauthorized | โ | Re-authenticate |
403 Forbidden | โ | Check permissions |
404 Not Found | โ | Check resource ID |
409 Conflict | โ | Resolve conflict |
429 Rate Limited | โ | Wait and retry |
500 Server Error | โ | Retry with backoff |
502 Bad Gateway | โ | Retry with backoff |
503 Unavailable | โ | Retry with backoff |