Skip to content

Error Handling

Error Response Format

When an error occurs, the API returns error information in the following format:

{
"error": "error_code",
"error_description": "Detailed error description",
"details": {
"field": "Additional information (optional)"
}
}

Field Description

FieldTypeDescription
errorstringError code (machine-readable)
error_descriptionstringError description (human-readable)
detailsobjectAdditional error details (optional)

Errors by HTTP Status Code

400 Bad Request

When the request format is invalid:

{
"error": "invalid_request",
"error_description": "Invalid JSON in request body"
}

401 Unauthorized

When authentication fails:

{
"error": "unauthorized",
"error_description": "Authentication token is invalid or expired"
}

403 Forbidden

When permissions are insufficient:

{
"error": "forbidden",
"error_description": "You do not have permission to perform this operation"
}

404 Not Found

When resource is not found:

{
"error": "not_found",
"error_description": "The specified user was not found"
}

409 Conflict

When a resource conflict occurs:

{
"error": "conflict",
"error_description": "This email address is already in use"
}

422 Unprocessable Entity

For validation errors:

{
"error": "validation_error",
"error_description": "Invalid input data",
"details": {
"email": "Please enter a valid email address",
"name": "Name is required"
}
}

429 Too Many Requests

When rate limit is exceeded:

{
"error": "rate_limit_exceeded",
"error_description": "Rate limit exceeded",
"retry_after": 60
}

500 Internal Server Error

For server internal errors:

{
"error": "internal_error",
"error_description": "An internal error occurred. Please try again later."
}

Error Code Reference

Authentication & Authorization Errors

Error CodeHTTP StatusDescription
unauthorized401Invalid or missing authentication credentials
token_expired401Token has expired
token_revoked401Token has been revoked
forbidden403Insufficient permissions
insufficient_scope403Required scope is missing

Resource Errors

Error CodeHTTP StatusDescription
not_found404Resource not found
user_not_found404User not found
client_not_found404Client not found
organization_not_found404Organization not found
role_not_found404Role not found
policy_not_found404Policy not found
flow_not_found404Flow not found

Validation Errors

Error CodeHTTP StatusDescription
invalid_request400Invalid request format
validation_error422Input data validation failed
invalid_email422Invalid email address format
invalid_password422Password does not meet requirements
invalid_json400JSON parsing failed

Conflict Errors

Error CodeHTTP StatusDescription
conflict409Resource conflict
email_already_exists409Email address is already in use
client_id_already_exists409Client ID is already in use
role_already_assigned409Role is already assigned

State Errors

Error CodeHTTP StatusDescription
user_suspended403User is suspended
user_locked403User is locked
client_disabled403Client is disabled
flow_inactive400Flow is inactive

Job Errors

Error CodeHTTP StatusDescription
job_not_found404Job not found
job_failed500Job execution failed
job_cancelled400Job was cancelled
import_failed422Import processing failed
export_failed500Export processing failed

System Errors

Error CodeHTTP StatusDescription
internal_error500Internal server error
service_unavailable503Service temporarily unavailable
database_error500Database error
timeout504Request timeout

Error Handling Best Practices

Retry Strategy

For transient errors (5xx), we recommend retrying with exponential backoff:

async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.status === 429) {
// Rate limit: wait for retry_after
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
await sleep(retryAfter * 1000);
continue;
}
if (response.status >= 500) {
// Server error: exponential backoff
await sleep(Math.pow(2, i) * 1000);
continue;
}
return response;
} catch (error) {
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000);
}
}
}

Error Logging

Log API errors appropriately:

try {
const response = await adminApi.createUser(userData);
} catch (error) {
console.error('User creation error:', {
error_code: error.error,
description: error.error_description,
details: error.details,
request_id: error.request_id
});
}

User Feedback

Display error messages in a user-friendly way:

function getErrorMessage(error) {
switch (error.error) {
case 'email_already_exists':
return 'This email address is already registered.';
case 'validation_error':
return Object.values(error.details).join('\n');
case 'rate_limit_exceeded':
return 'Too many requests. Please wait a moment.';
default:
return 'An error occurred. Please try again later.';
}
}

Debug Information

Request ID

All responses include an X-Request-ID header:

X-Request-ID: req_abc123xyz

Include this request ID when contacting support.

Debug Mode

In development environments, you can enable detailed error information:

Terminal window
curl -X POST "https://{tenant-domain}/api/admin/users" \
-H "Authorization: Bearer {token}" \
-H "X-Debug: true" \
-d '{...}'

Response:

{
"error": "validation_error",
"error_description": "Invalid input data",
"details": {
"email": "Please enter a valid email address"
},
"debug": {
"stack_trace": "...",
"request_body": {...},
"timestamp": "2024-01-22T10:30:00Z"
}
}