Errors
All error responses use a consistent shape:
{ "error": { "message": "Invalid API key", "type": "auth_error" }}Some errors — most notably wrong endpoint × model mismatches — include an optional details object. Existing integrations keep working off error.message and error.type; the details object is a backward-compatible addition.
{ "error": { "message": "The model \"google/gemini-3.1-flash-image\" does not support /v1/images/edits. Use /v1/images/generations instead. For image-to-image, try-on or image merging, send reference images via the 'file_ids' field (after uploading them through /v1/files), or via 'image_urls' for hosted URLs.", "type": "unsupported_operation", "details": { "param": "model", "model": "google/gemini-3.1-flash-image", "attempted_endpoint": "/v1/images/edits", "supported_endpoints": ["/v1/images/generations"], "suggested_endpoint": "/v1/images/generations", "hint": "For image-to-image, try-on or image merging, send reference images via the 'file_ids' field (after uploading them through /v1/files), or via 'image_urls' for hosted URLs.", "docs_url": "https://llmtr.com/docs/gateway/image-generation/" } }}Fields inside details:
| Field | Description |
|---|---|
param | The offending request field (usually model) |
model | Canonical model ID from the request |
attempted_endpoint | Endpoint the request was sent to |
supported_endpoints | Endpoints this model actually supports |
suggested_endpoint | Closest correct endpoint to retry against |
hint | Provider- and model-specific actionable note (e.g. use file_ids) |
docs_url | Documentation pointer for the relevant guide |
Retired model identifiers return HTTP 410 with replacement details:
{ "error": { "message": "Model \"mimo/mimo-v2-pro\" was retired on 2026-06-30. Use \"mimo/mimo-v2.5-pro\" instead.", "type": "model_retired", "details": { "model": "mimo/mimo-v2-pro", "replacement_model": "mimo/mimo-v2.5-pro", "retirement_date": "2026-06-30" } }}Error types
Section titled “Error types”| HTTP | type | Reason | What to do |
|---|---|---|---|
| 400 | invalid_request_error | Invalid JSON, missing field, unknown parameter | Fix the request and check the schema |
| 401 | auth_error | Invalid or revoked key | Generate a new key in the dashboard |
| 402 | insufficient_balance | Credit balance is too low | Top up from Dashboard > Billing |
| 403 | forbidden | The model is not available for this account | Verify model access |
| 404 | model_not_found | Unknown model value | Check the canonical ID (provider/model) |
| 410 | model_retired | Model identifier has been retired | Switch to error.details.replacement_model |
| 413 | request_too_large | Context window exceeded | Shorten the messages content |
| 429 | rate_limit_exceeded | Rate limit hit | Retry with exponential backoff |
| 500 | internal_error | Gateway internal error | Retry after a short delay |
| 502 | provider_error | Provider-side failure | Often transient, retry |
| 503 | provider_unavailable | Provider unreachable | Retry later |
| 504 | timeout | Request timed out | Request fewer tokens or try streaming |
Retry strategy
Section titled “Retry strategy”Retry only for 429, 500, 502, 503, 504.Backoff: exponential + jitter.Max retry: 3.Example (Python):
import time, randomfrom openai import OpenAI, APIStatusError
RETRIABLE = {429, 500, 502, 503, 504}
def call(client, payload, attempt=0): try: return client.chat.completions.create(**payload) except APIStatusError as e: if e.status_code in RETRIABLE and attempt < 3: time.sleep(2 ** attempt + random.random()) return call(client, payload, attempt + 1) raiseWhen implementing retries, also account for client-side timeouts, broken connections, and duplicate sends.