All ADL error responses use a standard envelope format. This chapter documents every error code, the HTTP status mapping, error details structure, and client handling guidance.
The error contract is stable across ADL versions. Client applications can rely on consistent error codes and response shapes for predictable error handling.
Attempt refresh token flow, then redirect to login
TOKEN_INVALID
Malformed or tampered token
Clear token, redirect to login
TOKEN_MISSING
No Authorization header
Redirect to login
Authorization (403)
error_code
Description
Client Action
FORBIDDEN
Insufficient permissions for operation
Show “access denied”, disable action
USER_SUSPENDED
Account suspended by admin
Show suspension notice, logout
GUARD_FAILED
State machine guard rejected transition
Disable transition button, show available transitions
FIELD_RESTRICTED
Write to restricted field
Mark field as read-only
Validation (422)
error_code
Description
Client Action
VALIDATION_ERROR
One or more fields failed validation
Show per-field errors from data
REQUIRED_FIELD
Required field missing
Highlight field as required
FIELD_TYPE_MISMATCH
Field value wrong type
Show type error on field
FIELD_TOO_LONG
String exceeds maxLength
Show character count, trim
FIELD_TOO_SHORT
String below minLength
Show minimum length requirement
PATTERN_MISMATCH
String doesn’t match pattern
Show format hint (e.g., “Email format required”)
VALUE_OUT_OF_RANGE
Number outside min/max
Show valid range
INVALID_ENUM_VALUE
Value not in enum
Show valid options
RULE_VIOLATION
Cross-field validation rule failed
Show rule message at form level
State Machine (422/403)
error_code
Description
Client Action
INVALID_TRANSITION
Transition not available from current state
Show available transitions only
FINAL_STATE
Record in terminal state, no transitions available
Hide all transition buttons
NO_STATE
Record has no state field value
Show error, refresh record
UNKNOWN_STATE
State value not defined in state machine
Show error, contact support
REQUIRED_FIELD_MISSING
Transition requires field not provided
Show required fields before transition
Resource (400/404)
error_code
Description
Client Action
NOT_FOUND
Record does not exist
Show “not found” message, redirect to list
MISSING_ID
No ID in path or body
Bug in client code
MISSING_PK
Composite primary key field missing
Provide all key fields
Conflict (409)
error_code
Description
Client Action
DUPLICATE
Unique constraint violation
Show “already exists” on duplicate field
CONCURRENT_MODIFICATION
Record modified since read
Reload record, show conflict resolution UI
Rate Limiting (429)
error_code
Description
Client Action
RATE_LIMITED
Too many requests
Show retry message, respect Retry-After header
Server Error (500)
error_code
Description
Client Action
INTERNAL_ERROR
Unexpected server error
Show error message, report to support
DATABASE_ERROR
Database operation failed
Show error, retry once
INTEGRATION_ERROR
External service error
Show error, retry with backoff
39.5 Validation Error Details
Field-Level Errors
{ "status": "error", "code": 422, "error_code": "VALIDATION_ERROR", "error_message": "Validation failed", "data": { "title": { "code": "required", "message": "Title is required" }, "email": { "code": "pattern", "message": "Invalid email format" }, "age": { "code": "min", "message": "Age must be at least 18" } }}
The data object is keyed by field name. Each field error contains:
code — validation rule that failed
message — human-readable error message
Cross-Field Validation Errors
{ "status": "error", "code": 422, "error_code": "VALIDATION_ERROR", "error_message": "Validation failed", "data": { "dateOrder": { "code": "rule_failed", "message": "End date must be after start date" }, "budgetCheck": { "code": "rule_failed", "message": "Total budget cannot exceed $100,000" } }}
Cross-field validation rules use the rule name as the key.
39.6 State Machine Error Details
Invalid Transition
{ "status": "error", "code": 422, "error_code": "INVALID_TRANSITION", "error_message": "Transition 'publish' is not available from state 'archived'", "data": { "transition": "publish", "currentState": "archived", "availableTransitions": ["restore"] }}
The retryAfter field indicates seconds to wait before retrying. Also available in the Retry-After HTTP header.
39.9 Client Handling Guidance
Global Error Interceptor
Implement a global error handler that intercepts all API responses:
async function handleResponse(response: Response) { if (!response.ok) { const error = await response.json(); switch (error.code) { case 401: if (error.error_code === 'TOKEN_EXPIRED') { // Attempt refresh const refreshed = await refreshToken(); if (refreshed) { // Retry original request return retryRequest(response); } } // Redirect to login window.location.href = '/login'; break; case 403: if (error.error_code === 'USER_SUSPENDED') { // Show suspension notice showSuspensionModal(); } else { // Show access denied showError('Access denied'); } break; case 422: // Show validation errors showValidationErrors(error.data); break; case 429: // Respect rate limit const retryAfter = error.data.retryAfter || 60; await sleep(retryAfter * 1000); return retryRequest(response); case 500: case 502: case 503: // Show error, report to monitoring reportError(error); showError('Server error. Please try again.'); break; } throw new APIError(error); } return response.json();}
Validation Error Display
function showValidationErrors(details: Record<string, ValidationError>) { // Clear previous errors clearErrors(); for (const [field, error] of Object.entries(details)) { const input = document.querySelector(`[name="${field}"]`); if (input) { // Show error next to field showFieldError(input, error.message); } else { // Cross-field validation — show at form level showFormError(error.message); } }}