ACAI returns structured JSON errors with consistent status codes. This page documents every error you may encounter and how to handle it.
All errors follow the OpenAI error format. The response body is JSON with an error object:
{
"error": {
"message": "Human-readable description of what went wrong",
"type": "error_type",
"code": "specific_error_code"
}
}Returned when a request violates a compliance policy — content safety, prompt injection, or PII policy configured to block.
{
"error": {
"message": "Request blocked by content safety policy: violence score 0.92 exceeds threshold 0.5",
"type": "guardrail_violation",
"code": "content_safety_block"
}
}Possible codes:
content_safety_block — Content safety score exceeded thresholdprompt_injection_detected — Prompt injection attempt blockedpii_policy_block — PII detected and policy set to block (not redact)classification_mismatch — Request classification below API key's minimum floorHow to handle
try:
response = client.chat.completions.create(...)
except openai.BadRequestError as e:
body = e.body # parsed JSON error
if body.get("error", {}).get("code") == "content_safety_block":
print("Content was blocked by safety policy")
elif body.get("error", {}).get("code") == "prompt_injection_detected":
print("Prompt injection attempt was blocked")Missing or invalid API key. Keys must start with dai_sk_.
{
"error": {
"message": "Invalid API key. Get one at agilecloud.ai/dashboard",
"type": "authentication_error",
"code": "invalid_api_key"
}
}Common causes
Authorization: Bearer dai_sk_... headerThe requested model requires a higher subscription tier than your current plan.
{
"error": {
"message": "Model 'gpt-5' requires Business tier or above. Current tier: Pro",
"type": "permission_error",
"code": "tier_restricted"
}
}How to handle
Check the model's tier requirement at GET /api/v1/gateway/catalog or upgrade your plan at agilecloud.ai/pricing.
You have exceeded your per-minute request or token limit. The response includes Retry-After header.
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit-Requests: 20
X-RateLimit-Remaining-Requests: 0
X-RateLimit-Reset-Requests: 12s
{
"error": {
"message": "Rate limit reached: 20 RPM. Retry after 12 seconds.",
"type": "rate_limit_error",
"code": "rate_limit_exceeded"
}
}How to handle
import time
import openai
try:
response = client.chat.completions.create(...)
except openai.RateLimitError as e:
retry_after = int(e.response.headers.get("Retry-After", 60))
print(f"Rate limited. Retrying in {retry_after}s...")
time.sleep(retry_after)
response = client.chat.completions.create(...) # retry| Tier | Requests/min | Tokens/min |
|---|---|---|
| Free | 20 | 40K |
| Pro | 300 | 500K |
| Business | 1,000 | 5M |
| Enterprise | Custom | Custom |
The upstream model provider (Azure AI Foundry, OpenAI, Anthropic, etc.) returned an error or timed out. ACAI could not get a response from the inference backend.
{
"error": {
"message": "Backend error: upstream provider returned 503",
"type": "backend_error",
"code": "upstream_unavailable"
}
}How to handle
Retry with exponential backoff. If persistent, the upstream provider may be experiencing an outage. Check status.agilecloud.ai or try a different model.
ACAI is temporarily unable to handle requests — typically during deployments or maintenance windows.
{
"error": {
"message": "Service temporarily unavailable. Please retry.",
"type": "server_error",
"code": "service_unavailable"
}
}Every response (including errors) includes an X-Request-ID header. Include this ID when contacting support — it lets us trace the full request lifecycle through our audit logs.
X-Request-ID: req_a1b2c3d4-e5f6-7890-abcd-ef1234567890
error.code field for programmatic handling — not the message string.X-Request-ID from every failed request for debugging.