Error Handling
How to handle errors from the Aira API — error response format, common error codes, and SDK helpers.
Error Response Format
All Aira API errors follow a consistent JSON structure:
{
"error": {
"code": "AUTHENTICATION_FAILED",
"message": "Invalid or expired API key.",
"details": {}
},
"request_id": "req_abc123"
}error.code— A machine-readable error code (see table below).error.message— A human-readable description of what went wrong.error.details— An optional object with additional context (e.g., which field failed validation).request_id— A unique identifier for the request. Include this when contacting support.
Common Error Codes
| Code | HTTP Status | Description |
|---|---|---|
AUTHENTICATION_FAILED | 401 | API key is missing, invalid, or expired. |
FORBIDDEN | 403 | The authenticated key does not have permission for this action. |
NOT_FOUND | 404 | The requested resource does not exist. |
DUPLICATE_REQUEST | 409 | A request with the same idempotency key has already been processed. |
RATE_LIMITED | 429 | You have exceeded the allowed request rate. See Rate Limits. |
ENDPOINT_NOT_WHITELISTED | 403 | The target endpoint is not in your approved allowlist. |
MODEL_UNAVAILABLE | 503 | The requested model is temporarily unavailable. Retry after a short delay. |
VALIDATION_ERROR | 422 | The request body failed validation. Check error.details for field-level information. |
INTERNAL_ERROR | 500 | An unexpected server error occurred. Retry with exponential backoff. |
Example Error Response
A validation error with field-level details:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request body failed validation.",
"details": {
"fields": {
"models": "must contain at least 2 model identifiers",
"prompt": "must not be empty"
}
}
},
"request_id": "req_7xk29m"
}Handling Errors in the Python SDK
The Python SDK raises typed exceptions that you can catch directly:
import aira
client = aira.Client(api_key="your-api-key")
try:
result = client.actions.create(prompt="Evaluate this claim", models=["gpt-5.2", "claude-sonnet"])
except aira.AuthenticationError as e:
# 401 — check your API key
print(f"Auth failed: {e.message}")
except aira.RateLimitError as e:
# 429 — back off and retry
retry_after = e.retry_after # seconds
print(f"Rate limited. Retry after {retry_after}s")
except aira.ValidationError as e:
# 422 — inspect field errors
print(f"Validation: {e.message}", e.details)
except aira.APIError as e:
# catch-all for any other API error
print(f"[{e.code}] {e.message} (request_id={e.request_id})")Handling Errors in the TypeScript SDK
The TypeScript SDK throws typed error classes:
import Aira, { AuthenticationError, RateLimitError, ValidationError, APIError } from "aira-sdk";
const client = new Aira({ apiKey: "your-api-key" });
try {
const result = await client.actions.create({
prompt: "Evaluate this claim",
models: ["gpt-5.2", "claude-sonnet"],
});
} catch (err) {
if (err instanceof AuthenticationError) {
// 401
console.error("Auth failed:", err.message);
} else if (err instanceof RateLimitError) {
// 429
console.error(`Rate limited. Retry after ${err.retryAfter}s`);
} else if (err instanceof ValidationError) {
// 422
console.error("Validation:", err.message, err.details);
} else if (err instanceof APIError) {
// catch-all
console.error(`[${err.code}] ${err.message} (request_id=${err.requestId})`);
}
}Best Practices
- Always include the
request_idin bug reports or support tickets. - Retry on 429 and 503 with exponential backoff. The
Retry-Afterheader (or SDK helper) tells you how long to wait. - Do not retry on 401 or 403 — these indicate a configuration problem, not a transient failure.
- Validate inputs client-side before sending requests to avoid unnecessary 422 errors.