Every error from api.ambient.xyz maps to a specific cause and a specific
reaction.
Error taxonomy#
| Status | Signal in the body | What it means | What to do |
|---|---|---|---|
401 / 403 | authentication_error or similar | Key missing, invalid, or revoked | Re-check the key; create a new one at app.ambient.xyz/keys |
402 (or a 403 whose message mentions funds/quota) | "insufficient funds", "quota" | Account out of funds | Top up; check the funds wording before classifying a 403 as an auth failure |
400 | "context", "context_length", "maximum context", "too long" | Input exceeds the model's context window | Trim the prompt, or pick a larger-context model from GET /v1/models |
400 | "Unknown model", invalid_request_error | The model id isn't in the catalog (or has been retired) | Use an exact id from GET /v1/models (for example z-ai/glm-5.2) |
429 + "No workers available" or "Upstream request failed" | no-workers / upstream wording | Not a rate limit. The model has no capacity right now | Retry with short, jittered backoff, or fail over to another model listed on GET /v1/models; if it keeps failing for minutes, the model is down |
429 (plain) | rate-limit wording | You are sending too fast | Back off with jitter and retry |
5xx | None | Ambient-side failure | Retry cautiously; see below |
The two kinds of 429#
The distinction matters because the right reactions differ. A 429 whose
body says "No workers available" or "Upstream request failed" is a
capacity signal: your auth and pacing are fine, but no worker picked up the
request. Retry with short, jittered backoff, or fail over to another model
listed on GET /v1/models. If the same model keeps failing for minutes,
treat it as down. A plain 429 is classic rate limiting: slow down and
retry the same request with exponential backoff.
A capacity 429 looks like this:
{"error": {"message": "No workers available", "type": "upstream_error"}}The type can be upstream_error or rate_limit_exceeded for the same
condition, so key on the message wording, not the type. Ambient reports
capacity as 429 rather than 503 for compatibility with upstream routers
such as OpenRouter. A capacity 429 carries no
Retry-After header, and you don't need one: the body tells you which case
you are in, and short jittered backoff (or failover) is the right reaction
to a capacity error regardless.
Do not consult is_ready on GET /v1/models to decide what to do. It is an
OpenRouter routing flag, not an availability signal, and everything the
catalog lists is served; see
Models and readiness.
Retry guidance#
- Retry
502/503/504only for idempotent GETs (such asGET /v1/models), and only once or twice. - Do not blindly retry a timed-out completion POST. A request that timed
out on your side may still have been processed server-side, so a blind
retry can charge you twice for the same generation. If you must retry, do
it deliberately and log the
inference-idresponse header of every attempt so you can reconcile. - Treat mid-stream disconnects as truncation. Keep the partial output; see Streaming for stall and truncation detection.