Error handling
All errors return JSON with a standard envelope:
{
"error": {
"message": "Human-readable description",
"type": "error_category",
"code": "specific_error_code"
}
}
Full error catalogue
| HTTP | Type | Common codes | What it means | Recovery |
|---|---|---|---|---|
| 400 | invalid_request_error |
model_not_found, tos_required, email_not_verified |
Bad parameters in request body | Fix client code, don't retry |
| 401 | authentication_error |
authentication_error |
Missing / invalid / revoked API key | Check Authorization header; create new key if revoked |
| 402 | insufficient_quota |
insufficient_quota |
Account credit balance is Rp0 | Top up via dashboard (email hello@epithre.com) |
| 402 | insufficient_quota |
monthly_cap_exceeded |
This key hit its monthly_idr_cap for the month |
Raise the cap on this key in dashboard, or use a different key |
| 403 | permission_error |
account_suspended, email_not_verified, permission_error |
Account suspended OR endpoint needs admin OR email not verified | Check email inbox or contact support |
| 413 | request_too_large |
request_too_large |
Body exceeds limit: 1MB default, 25MB on /v1/embeddings (image), 50MB on /v1/images/* + /v1/files |
Reduce payload, split into batches |
| 422 | invalid_request_error |
invalid_request_error |
Stricter validation: oversize text with truncate: NONE, instruction + image, invalid pgvector content |
Fix specific constraint cited in message |
| 429 | rate_limit_error |
rpm_exceeded, rpd_exceeded, concurrency_exceeded, backend_busy |
Various rate limits hit | Exponential backoff (1s, 2s, 4s, ...). Raise limits in dashboard if persistent. |
| 500 | backend_error |
backend_error |
Internal failure | Retry once with backoff |
| 502 | backend_error |
backend_error |
Inference backend returned 5xx | Retry once |
| 503 | backend_unavailable |
backend_unavailable |
Backend not reachable (maintenance or outage) | Retry with longer backoff |
| 504 | backend_timeout |
backend_timeout |
Backend slow / hung | Retry with shorter prompt |
Recommended retry pattern
import time, random
from openai import APIError, RateLimitError, APITimeoutError, APIConnectionError
def call_with_retry(call_fn, max_retries=4):
for attempt in range(max_retries):
try:
return call_fn()
except RateLimitError:
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
except (APITimeoutError, APIConnectionError):
if attempt == max_retries - 1:
raise
time.sleep(1 + attempt)
except APIError as e:
if e.status_code >= 500 and attempt < max_retries - 1:
time.sleep(2 ** attempt)
else:
raise # 4xx (except 429): don't retry
raise Exception("retry exhausted")
What NOT to retry
- 400, 401, 402, 403, 422: your request is wrong. Retrying won't help.
- 405 (rare): wrong HTTP method.
400 model_not_found: badmodelvalue.
Reporting bugs
Include in your report:
X-Request-IDheader from the response, orchatcmpl-*ID from the response body- HTTP status + full error JSON
- Approximate timestamp (UTC preferred)
- The request body if possible (redact sensitive content)
Email: hello@epithre.com with subject "API issue".