Key facts
| Error schema | {"error":{"message","type","code","param"}} — JSON only, never HTML |
| Retryable | 429 (Retry-After), 500, 502 and 503 — with backoff and jitter |
| Not retryable | 400 invalid request, 401 bad key, 403 missing scope, 404 unknown model, 413 body too large |
| Idempotency | Idempotency-Key on POST endpoints returns the cached result for 24 hours |
| Conflict | 409 means the same Idempotency-Key was reused with a different body |
| Body limit | Maximum request body is 16 MB; trim conversation history or split the request |
| Context errors | Context-window failures return 400 with exact token counts in the message |
| Product status | Live |
TL;DR
- Parse one error shape for every provider and the gateway.
- Retry 429/500/502/503 with backoff; never blind-retry 4xx.
- Idempotency-Key makes POST retries safe for 24 hours.
- Retry-After beats your own backoff schedule when present.
- Log request ID, model and key ID so support can trace failures.
How it works, step by step
- Wrap every call in a parser for the OpenAI error schema and read code and message.
- Classify statuses: retryable (429, 500, 502, 503) versus fixable (others).
- Send Idempotency-Key on all POST requests with a fresh UUID per logical operation.
- Retry with exponential backoff plus jitter, capped at a few attempts per request.
- Honor Retry-After when it is present and cancel the retry if the work is no longer needed.
- Log request ID, model, key ID and status for every failure to make incidents traceable.
- Fix 401/403 in configuration, and reduce context for 400 context-window errors.
Original data
Try it yourself
Open the OpenAI-compatible API tester →
The status codes, decoded
- 400 — malformed JSON or invalid parameter; validate locally and check the parameter named in the error.
- 401 — missing or invalid API key; check the Authorization header and key state.
- 403 — the key lacks the required scope; add it or use a differently scoped key.
- 404 — model or resource not found; list /v1/models and correct the model name.
- 409 — Idempotency-Key reused with a different body; generate a fresh key per logical request.
- 413 — body exceeds the 16 MB limit; trim or split the request.
- 429 — fair-use rate limit hit; honor Retry-After and back off.
- 500 / 502 / 503 — internal error, provider failure after failover, or upstream down; retry with backoff and check /status for incidents.
A retry policy you can ship
Blind retries multiply incidents. The policy that works:
- Retry only 429, 500, 502 and 503 — plus network timeouts.
- Use exponential backoff with full jitter, starting around 500 ms and capping at a few attempts.
- When
Retry-Afteris present, wait at least that long. - Attach
Idempotency-Keyso a retried POST returns the cached response rather than repeating the work. - Set a per-request deadline so a retry chain cannot outlive the user's patience.
- Stop retrying once the result is no longer useful — for interactive requests, a fast failure beats a stale success.
Debugging 400, 401 and 403 quickly
These are configuration or payload bugs and reproduce immediately:
- 401: the header is missing, malformed, or the key was rotated and the old secret is still deployed. Print the first six characters of the key in logs to confirm identity — never the whole key.
- 403: the key is valid but the scope list does not include the endpoint's required scope, for example a key without
chat:writecalling chat completions. - 400 context: the message includes exact token counts. Reduce history, lower
max_tokens, or summarise older turns. - 400 invalid parameter: compare against the API reference; model-specific parameters such as unsupported response formats are rejected rather than ignored.
Reproduce with curl -i or the API tester before changing application code.
What to log for fast incidents
Log the request ID, model, key ID (not the secret), project, region, status, latency and retry attempt for every call. Plugsky returns request metadata in responses and logs the same fields server-side, so support can correlate your report with platform telemetry. For repeated 502s, check the status page before opening a ticket: failover usually resolves transient provider failures, and incident history tells you whether you are in one.
Honest comparison
| Failure mode | Plugsky handling | Typical API | Self-managed stack |
|---|---|---|---|
| Error format | One OpenAI-schema error object | Vendor-specific shapes | You standardise |
| Rate limit signal | 429 with Retry-After | Varies; often 429 only | Custom headers |
| Safe POST retries | Idempotency-Key cached 24 hours | Inconsistent support | You build it |
| Upstream failure | Automatic failover first | Provider outage is final | You route |
| Body size limit | 16 MB with a clear 413 | Varies | Your limits |
| Traceability | Request IDs plus per-request logs | Usually request IDs | Custom telemetry |
Frequently asked questions
What does a Plugsky error response look like?
All errors use {"error":{"message","type","code","param"}} with an HTTP status code, JSON only — never an HTML error page — so one parser covers every endpoint.
Which errors should I retry?
Retry 429, 500, 502 and 503 with exponential backoff and jitter. Do not retry 400, 401, 403, 404 or 413; those require a fix in the request or configuration.
How does Idempotency-Key help?
Send it on POST requests and resending the same key returns the cached result for 24 hours, so a timeout-then-retry cannot create duplicate work. Reusing a key with a different body returns 409.
What is the maximum request size?
The maximum request body is 16 MB. Larger inputs return 413; trim conversation history or split the payload into multiple calls.
How do I handle a context-window error?
It returns 400 with exact token counts in the message. Reduce history, summarise older turns, or lower max_tokens, then retry once.
Should I retry a 502?
Yes, with backoff. 502 means a provider failed after auto-failover was attempted; check the status page if it persists and include the request ID in any ticket.
Do SDKs retry automatically?
Plugsky SDKs retry with exponential backoff on retryable statuses. Custom HTTP clients should implement the same policy and add jitter.
How do I debug a 403?
The key is valid but missing a scope. Compare the key's comma-separated scope list with the endpoint you are calling and add the narrowest scope that works.