Guides
Error Handling
All API errors return a consistent JSON envelope. Use the type field to branch your error-handling logic.
Error envelope
json
{
"error": {
"type": "invalid_request_error",
"code": "missing_field",
"message": "\"messages\" is required.",
"param": "messages"
}
}Every non-2xx response has an error object with these fields:
| Error type | HTTP | Description |
|---|---|---|
| type | 0 | Broad category — use this for programmatic branching. |
| code | 0 | Specific machine-readable reason within the type. |
| message | 0 | Human-readable description. |
| param | 0 | Which request parameter caused the error, or null. |
Error types
| Error type | HTTP | Description |
|---|---|---|
| invalid_request_error | 400 | The request was malformed — missing field, bad value, unsupported parameter. |
| authentication_error | 401 | API key is missing, invalid, or revoked. |
| permission_error | 403 | Key does not have permission for this operation. |
| not_found_error | 404 | Endpoint or resource not found. |
| rate_limit_error | 429 | Too many requests — slow down and retry after the Retry-After header value. |
| api_error | 500 | Internal server error. Retry with exponential backoff. |
| overloaded_error | 503 | Inference capacity temporarily unavailable. Retry shortly. |
Retryable errors
Only retry on these status codes: 429, 500, 502, 503, 504. Never retry 400 or 401 — those won't resolve themselves.
Tip:For
429, read the Retry-After response header — it tells you exactly how many seconds to wait. The SDKs do this automatically.Python
python
import time
from satryx import Satryx, RateLimitError, APIConnectionError
client = Satryx()
def chat_with_retry(messages, retries=3):
for attempt in range(retries):
try:
return client.chat.completions.create(
model="llama-3.1-70b",
messages=messages,
)
except RateLimitError as e:
wait = e.retry_after_seconds or (2 ** attempt)
time.sleep(wait)
except APIConnectionError:
if attempt == retries - 1:
raise
time.sleep(2 ** attempt)
raise RuntimeError("Exhausted retries")TypeScript
typescript
import Satryx, { RateLimitError, APIConnectionError } from "@satryx/sdk";
const client = new Satryx();
async function chatWithRetry(messages: any[], retries = 3) {
for (let attempt = 0; attempt < retries; attempt++) {
try {
return await client.chat.completions.create({
model: "llama-3.1-70b",
messages,
});
} catch (err) {
if (err instanceof RateLimitError) {
const wait = (err.retryAfterSeconds ?? Math.pow(2, attempt)) * 1000;
await new Promise((r) => setTimeout(r, wait));
} else if (err instanceof APIConnectionError && attempt < retries - 1) {
await new Promise((r) => setTimeout(r, Math.pow(2, attempt) * 1000));
} else {
throw err;
}
}
}
throw new Error("Exhausted retries");
}SDK exception hierarchy
text
SatryxError
└── APIError
├── APIConnectionError # network failure
└── APIStatusError # HTTP error response
├── BadRequestError # 400
├── AuthenticationError # 401
├── PermissionError # 403
├── NotFoundError # 404
├── RateLimitError # 429 (.retry_after_seconds)
├── InternalServerError # 500
└── OverloadedError # 503See the Python SDK and TypeScript SDK pages for import examples.