Error Handling
The MATIH Platform uses a structured error response format across all services. Every error response follows the same envelope structure, uses typed error codes, and includes enough context for debugging without leaking sensitive internal details.
Error Response Structure
All error responses use the standard envelope with success: false:
{
"success": false,
"error": {
"code": "RESOURCE_NOT_FOUND",
"category": "CLIENT_ERROR",
"message": "Dashboard with ID 'dash-xyz' not found",
"details": {
"resourceType": "Dashboard",
"resourceId": "dash-xyz"
}
},
"metadata": {
"timestamp": "2026-02-12T10:30:00Z",
"requestId": "req-abc-123",
"version": "v1"
}
}Error Categories
| Category | HTTP Status Range | Description |
|---|---|---|
CLIENT_ERROR | 400-499 | The request was malformed, unauthorized, or targeted a missing resource |
SERVER_ERROR | 500-599 | An internal error occurred that was not caused by the client |
VALIDATION_ERROR | 400 | Input validation failed |
AUTHORIZATION_ERROR | 401, 403 | Authentication or permission failure |
Error Codes
| Error Code | HTTP Status | Description |
|---|---|---|
VALIDATION_FAILED | 400 | Request body failed schema validation |
INVALID_PARAMETER | 400 | Query parameter has invalid value |
UNAUTHORIZED | 401 | Missing or invalid JWT token |
TOKEN_EXPIRED | 401 | JWT access token has expired |
FORBIDDEN | 403 | Authenticated but lacks required permission |
TENANT_MISMATCH | 403 | Attempted to access a resource from another tenant |
RESOURCE_NOT_FOUND | 404 | Requested resource does not exist |
CONFLICT | 409 | Resource already exists or concurrent modification |
RATE_LIMITED | 429 | Per-tenant rate limit exceeded |
INTERNAL_ERROR | 500 | Unhandled internal error |
SERVICE_UNAVAILABLE | 503 | Downstream service is unreachable |
GlobalExceptionHandler
The GlobalExceptionHandler in commons-java catches all exceptions and translates them to structured error responses. This ensures that no unhandled exception leaks stack traces or internal details to the client.
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleUnhandledException(Exception ex) {
log.error("Unhandled exception", ex);
return ResponseEntity.status(500).body(
ErrorResponse.of(ErrorCode.INTERNAL_ERROR, "An internal error occurred")
);
}Exception Mapping
| Exception Type | Error Code | HTTP Status |
|---|---|---|
MethodArgumentNotValidException | VALIDATION_FAILED | 400 |
IllegalArgumentException | INVALID_PARAMETER | 400 |
AuthenticationException | UNAUTHORIZED | 401 |
AccessDeniedException | FORBIDDEN | 403 |
ResourceNotFoundException | RESOURCE_NOT_FOUND | 404 |
DataIntegrityViolationException | CONFLICT | 409 |
RateLimitExceededException | RATE_LIMITED | 429 |
Exception (catch-all) | INTERNAL_ERROR | 500 |
Validation Errors
Validation errors include field-level details:
{
"success": false,
"error": {
"code": "VALIDATION_FAILED",
"category": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": {
"fieldErrors": [
{
"field": "name",
"message": "must not be blank"
},
{
"field": "email",
"message": "must be a valid email address"
}
]
}
}
}Error Handling in Python Services
Python services (FastAPI) use a similar pattern with Pydantic validation and custom exception handlers:
@app.exception_handler(ResourceNotFoundException)
async def resource_not_found_handler(request, exc):
return JSONResponse(
status_code=404,
content={
"success": False,
"error": {
"code": "RESOURCE_NOT_FOUND",
"category": "CLIENT_ERROR",
"message": str(exc)
}
}
)Security-Sensitive Errors
The platform follows these principles for security-sensitive errors:
| Principle | Implementation |
|---|---|
| No stack traces in responses | GlobalExceptionHandler catches all exceptions |
| No internal details leakage | Error messages are user-friendly, not technical |
| Generic auth errors | Login failures return generic "invalid credentials" message |
| Tenant isolation violations logged | Cross-tenant access attempts trigger security alerts |
Related Pages
- REST Conventions -- URL patterns and response format
- Authentication -- Authentication error flows
- Data Flow -- Error handling in the request lifecycle