The AIWave API reports failures with standard HTTP status codes and a JSON body shaped like the OpenAI error envelope. This page lists every status you can encounter, what causes it, and whether retrying is worthwhile — the distinction that matters most when you are writing retry logic.
{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found"
}
}
| Status | Meaning | Code | Cause |
|---|---|---|---|
400 | Bad Request | invalid_request_error | Malformed JSON, a missing messages array, or a parameter the model does not accept. |
401 | Unauthorized | invalid_api_key | The Authorization header is missing, malformed, or the key has been revoked. |
403 | Forbidden | permission_denied | The key is valid but is not permitted to call this model or endpoint. |
404 | Not Found | model_not_found | The model value does not match any served model ID. Model IDs are versioned and do change. |
408 | Request Timeout | timeout | The upstream provider did not respond inside the gateway timeout, typically on very long prompts. |
429 | Too Many Requests | rate_limit_exceeded | You exceeded a rate limit, or the account balance is exhausted. |
500 | Internal Server Error | server_error | An unexpected failure inside the gateway. |
502 | Bad Gateway | upstream_error | The upstream model provider returned an invalid response. |
503 | Service Unavailable | service_unavailable | The upstream provider is overloaded or in maintenance. This is the most common transient failure in practice. |
Retrying a permanent error wastes quota and hides bugs. The rule of thumb: retry
408, 429, 500, 502 and 503; never retry
400, 401, 403 or 404 without changing the request.
import time, random
from openai import OpenAI, APIStatusError
client = OpenAI(api_key="sk-YOUR_KEY", base_url="https://aiwave.live/v1")
RETRYABLE = {408, 429, 500, 502, 503}
def chat(messages, model="deepseek-v4-pro", fallback="deepseek-v4-flash", attempts=5):
for i in range(attempts):
try:
return client.chat.completions.create(model=model, messages=messages)
except APIStatusError as e:
if e.status_code not in RETRYABLE:
raise # permanent: fix the request, do not loop
if i == attempts - 2 and fallback:
model = fallback # last-ditch: switch provider
time.sleep((2 ** i) + random.random())
raise RuntimeError("all retries exhausted")
Because every model behind this gateway accepts the same request body, the fallback above is a one-word change. That is the cheapest available insurance against a single provider having a bad day.
What it means. Malformed JSON, a missing messages array, or a parameter the model does not accept.
What to do. Log the full response body — it names the offending field. Validate the payload before retrying; retrying an identical bad request will fail identically.
What it means. The Authorization header is missing, malformed, or the key has been revoked.
What to do. Check the header is exactly Authorization: Bearer sk-.... Do not retry automatically — a retry loop on 401 just burns quota.
What it means. The key is valid but is not permitted to call this model or endpoint.
What to do. Confirm the model appears in GET /v1/models for your key. Fall back to a model you do have access to.
What it means. The model value does not match any served model ID. Model IDs are versioned and do change.
What to do. Never hard-code a model list. Call GET /v1/models at startup and fail loudly if your configured model is absent.
What it means. The upstream provider did not respond inside the gateway timeout, typically on very long prompts.
What to do. Shorten the prompt, enable streaming so partial output arrives early, or retry with backoff.
What it means. You exceeded a rate limit, or the account balance is exhausted.
What to do. Back off exponentially with jitter. See rate limits for a working retry implementation.
What it means. An unexpected failure inside the gateway.
What to do. Safe to retry with backoff. If it persists across models, the problem is the gateway rather than one provider.
What it means. The upstream model provider returned an invalid response.
What to do. Retry, then fall back to a different model. The request body is identical across providers, so fallback is a one-line change.
What it means. The upstream provider is overloaded or in maintenance. This is the most common transient failure in practice.
What to do. Retry with exponential backoff, and keep a second model configured as a fallback so a single provider outage does not take your app down.