Error codes
Every error from Orux AI is normalized into a single shape, regardless of which upstream produced it.
We never surface raw upstream errors. Instead, we translate every failure into a stable Orux AI code so you can write one catch block and have it work across providers.
Error shape#
Errors are returned as JSON with a top-level "error" object. type groups them (auth_error, rate_limit_error, invalid_request_error, api_error). code is the stable string you switch on. param names the offending field, if any. channel names the upstream that failed, if relevant.
{
"error": {
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"message": "You exceeded your current QPS of 10.",
"channel": null,
"param": null
}
}All error codes#
| Code | HTTP | Type | When | What to do |
|---|---|---|---|---|
invalid_api_key | 401 | auth_error | Authorization header missing, malformed, or the key is unknown. | Check the Authorization: Bearer sk-app-... header and that the key still exists in the dashboard. |
sk_disabled | 401 | auth_error | Key exists but is disabled. | Re-enable it in the dashboard, or create a new key. |
sk_expired | 401 | auth_error | Key has an explicit expiry that has passed. | Rotate to a new key. |
ip_not_allowed | 403 | auth_error | Caller IP is outside the key’s allow-list. | Add the CIDR to the allow-list, or call from an approved IP. |
admin_token_required | 401 | auth_error | Tried to call /api/admin/* with a business sk. | Admin APIs require a separate admin token, not a business sk. |
rate_limit_exceeded | 429 | rate_limit_error | Account-level QPS exceeded. Reserved for future use. | Back off with exponential delay + jitter. |
concurrency_exceeded | 429 | rate_limit_error | Too many in-flight requests for this user (default cap: 3 across all keys). | Wait for an in-flight call to finish, or ask an admin to raise the per-user concurrency cap. |
quota_exceeded | 429 | rate_limit_error | Monthly token quota or Credits balance exhausted. | Top up Credits, or raise the account monthly token cap. |
channel_queue_full | 429 | rate_limit_error | The model id has no healthy upstream channel. | Retry after a few seconds. |
model_not_found | 404 | invalid_request_error | The model model id does not exist or is not enabled for your account. | List /api/v1/models for the available model ids. |
invalid_param | 400 | invalid_request_error | A request field is missing, the wrong type, or out of range. | See error.param for the offending field; correct the request. |
context_too_long | 400 | invalid_request_error | Prompt + max_tokens exceeds the model context window. | Shorten the conversation, lower max_tokens, or use a longer-context model. |
unsupported_capability | 400 | invalid_request_error | You requested e.g. tools on a model that does not support tool calling. | Pick a model whose capabilities include the feature; see /docs/models. |
content_filter | 400 | invalid_request_error | Upstream policy blocked the request or response. | Refine the prompt; sensitive categories vary by provider. |
task_not_found | 404 | invalid_request_error | GET /api/v1/tasks/{id} for a task that does not belong to this account or has expired. | Re-submit, or check the id. |
upstream_error | 502 | api_error | Upstream returned a non-retryable error we could not classify. | Retry once; if it persists, email hello@orux.top with the failing request/response JSON. |
channel_outage | 503 | api_error | All channels for this model id are circuit-broken or unhealthy. | Retry in 30–60s; the breaker auto-closes after the cool-down. |
upstream_timeout | 504 | api_error | Upstream did not return in time. We retry once before surfacing this. | Reduce max_tokens, or retry with backoff. |
internal_error | 500 | api_error | Our side. Should not happen; the response JSON carries enough to trace it. | Retry once and notify hello@orux.top with the response JSON if persistent. |
webhook_replay | 400 | invalid_request_error | Webhook timestamp is older than 5 minutes — replay protection. | Trust only recent signed events; ours always carry a fresh X-Orux-Timestamp. |
Handling errors#
A safe default: retry once on api_error and rate_limit_error with exponential backoff and jitter; surface auth_error and invalid_request_error to the user. When you contact support, paste the failing JSON body — the error object includes enough context to trace the call.
Catch + retry pattern
import time, random, requests
def call_with_retry(payload, max_retries=5):
delay = 0.2
for attempt in range(max_retries):
r = requests.post(
"https://orux.top/api/v1/chat/completions",
headers={"Authorization": "Bearer $ORUX_API_KEY"},
json=payload,
timeout=60,
)
if r.status_code < 500 and r.status_code != 429:
return r.json()
# exponential backoff with jitter
time.sleep(delay + random.uniform(0, delay))
delay = min(delay * 2.5, 10)
r.raise_for_status()