~/docs/api_reference/errors.md
#Errors
When something goes wrong, the API returns a JSON body in this shape:
json
{
"error": {
"type": "rate_limit_exceeded",
"code": "gremlin_in_the_pipes",
"message": "too many requests, tall one. come back in 12s.",
"param": null,
"retry_after": 12
}
}##Error types
| HTTP | Type | Retryable | Description |
|---|---|---|---|
| 400 | invalid_request_error | no | Malformed body, missing fields, unsupported parameter |
| 401 | authentication_error | no | Bad / missing / revoked API key |
| 403 | permission_error | no | Key lacks required scope |
| 404 | not_found_error | no | Model/resource doesn't exist |
| 409 | conflict_error | no | Concurrent modification of a resource |
| 422 | validation_error | no | Body parsed but failed validation |
| 429 | rate_limit_exceeded | yes | Too many requests / tokens / concurrent calls |
| 429 | quota_exceeded | no | Monthly billing quota hit. Upgrade or wait. |
| 500 | server_error | yes | Generic server failure |
| 502 | upstream_error | yes | Underlying inference cluster unreachable |
| 503 | service_unavailable | yes | Maintenance or capacity throttling |
| 503 | horde_unavailable | yes | Specific model tier overloaded โ try a different one |
| 504 | request_timeout | yes | Inference exceeded timeout (default 60s) |
##Codes (gob-flavored)
Every error includes a stable machine-readable code. The message is gob-flavored prose meant for humans/logs โ don't parse it, parse the code.
| Code | Type | Notes |
|---|---|---|
invalid_api_key | authentication_error | |
expired_api_key | authentication_error | Rotated keys expire after 24h |
revoked_api_key | authentication_error | |
wrong_password_to_cave | authentication_error | Auth header missing/malformed |
scope_required | permission_error | |
model_not_found | not_found_error | |
context_length_exceeded | invalid_request_error | Reduce messages or pick a larger-context model |
invalid_mining_depth | invalid_request_error | Must be 1โ7 |
gremlin_in_the_pipes | rate_limit_exceeded | RPM limit hit. Includes retry_after |
too_many_tokens | rate_limit_exceeded | TPM limit hit |
no_treasure_in_hoard | quota_exceeded | Monthly quota gone |
cave_collapsed | server_error | Generic 500 โ retry |
horde_unavailable | service_unavailable | |
goblin_distracted | server_error | Generation aborted mid-stream. Retry. |
safety_filter_triggered | invalid_request_error | Input or output blocked by safety layer |
##Retry strategy
For all retryable errors, use exponential backoff with jitter:
python
import time, random
from gpt_gob import GPTGob, GobError
client = GPTGob(api_key="gob-...")
def with_retry(fn, max_attempts=5):
for attempt in range(max_attempts):
try:
return fn()
except GobError as e:
if not e.is_retryable or attempt == max_attempts - 1:
raise
wait = e.retry_after or (2 ** attempt + random.random())
time.sleep(wait)The official SDKs do this automatically with sensible defaults (max_attempts=3, base delay 1s). You can configure or disable it:
python
client = GPTGob(api_key="gob-...", max_retries=5)javascript
const client = new GPTGob({
apiKey: process.env.GOB_API_KEY,
maxRetries: 5,
});##The `X-Request-Id` header
Every response carries an X-Request-Id header. Include it when contacting support โ it's the only way we can trace a specific call through our infrastructure.
text
X-Request-Id: req_8kQm3F9pLxN2vH7w