AICodeDog
Reliability

Errors & retries

Required reading for production: what each status code means, whether to retry, how to back off, and what to do when context overflows.

Error response format

All errors return JSON, identical in shape to OpenAI:

json
{ "error": { "type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Rate limit reached. Please retry after 12s.", "param": null } }

Status-code cheat-sheet

CodeTypeRetryableNotes / handling
400invalid_requestnoBad parameters. Read the message field and resend with a fix.
401authenticationnoKey missing / wrong / disabled. Check the Authorization header.
402payment_requirednoBalance exhausted. Top up in the console.
403permission_deniednoIP not in allowlist / model not enabled.
404not_foundnoUnknown model slug. Check /models for the live catalog.
408timeoutyesClient didn't read the response within 5 minutes. Use streaming.
429rate_limityes (with back-off)Rate limit hit. Honour the Retry-After header.
500server_erroryesSomething went wrong on our side. Exponential back-off retry.
502upstream_erroryes (auto fallback)Upstream model provider failed. We auto-tried alternate routes — if you got this, every route is down. Retry or switch model.
503overloadedyesOverloaded. Wait a few seconds and retry.

Retry strategy

General rules:

  • Don't retry 4xx (except 408, 429).
  • Always retry 5xx.
  • Max 3 attempts. Beyond that, let it bubble up to caller logic.
  • Exponential back-off + jitter: 1s → 2s → 4s with ±20% jitter to avoid synchronised retry stampedes.
  • Respect Retry-After: when 429 / 503 carry the header, wait the duration it specifies.
python
import time, random from openai import OpenAI, APIError, RateLimitError client = OpenAI(api_key="<KEY>", base_url="https://api.aicodedog.com/v1") def chat_with_retry(**kwargs): last_err = None for attempt in range(3): try: return client.chat.completions.create(**kwargs) except RateLimitError as e: wait = (2 ** attempt) * (1 + random.uniform(-0.2, 0.2)) time.sleep(wait) last_err = e except APIError as e: if e.status_code and 500 <= e.status_code < 600: wait = (2 ** attempt) * (1 + random.uniform(-0.2, 0.2)) time.sleep(wait) last_err = e else: raise # 4xx is not recoverable raise last_err

Context too long

If your messages + max_tokens exceed the model's context window, you immediately get 400 with code: "context_length_exceeded".

  • Short term: truncate history (keep the system message + recent N turns).
  • Medium term: swap to a longer-context model like Kimi-K2.6 (200K) or claude-opus-4-1 (200K).
  • Long term: move to RAG (see Embeddings) — chunk and index long documents, retrieve on demand.
Idempotency
Our API is idempotent-safe — retrying the same request never charges you twice (failed attempts aren't billed; only successful responses are). Your business logic, however, might not be idempotent (e.g. forwarding the reply to a downstream webhook); add your own request_id dedupe for critical calls.