Errors
routeur.ai returns short, JSON-shaped errors with a stable error.code and a human-readable error.message. Raw upstream provider error bodies are never relayed to callers — you'll always see a routeur.ai-shaped envelope.
Error shape
{
"error": {
"code": "blocked_by_dlp",
"message": "dlp:credit_card_redact",
"type": "routeur_error"
}
}
Status & codes
invalid_requestMalformed JSON or missing required fields such as messages.
unauthorizedMissing or unknown routeur.ai bearer token. See Authentication.
embeddings_unsupportedThe resolved model does not support embeddings.
billing_inactiveThe organisation's subscription is cancelled. See Limits and quotas.
blocked_by_dlpDLP blocked the request before the upstream call. The matching rule slug is in error.message.
blocked_by_shieldA prompt-shield rule matched the input — for example an instruction-override or encoded-payload attempt.
blocked_by_classifierA classifier rule's score threshold was exceeded on the input.
blocked_by_moderationThe upstream model answered but output moderation blocked the response from reaching the caller.
model_not_foundUnknown model id, or a model not activated for your workspace.
body_too_largeRequest body exceeded the cap — 5 MiB for chat completions, 10 MiB for embeddings.
allowance_exceededMonthly allowance and overage guardrail both reached. See Limits and quotas.
upstream_rate_limitedThe upstream provider rate-limited the call. Retry with backoff.
provider_unconfiguredNo credential is configured for the resolved provider.
provider_unavailableThe upstream provider could not be reached.
upstream_errorNon-timeout upstream failure.
overloadedThe gateway's in-flight cap was reached. Carries Retry-After; retry with jittered backoff.
upstream_errorThe upstream call hit routeur.ai's per-request timeout. Safe to retry idempotently.
There is no rate_limited code and no forbidden code. A revoked key returns
401 unauthorized, the same as an unknown one.
Errors during a stream
For streamed requests ("stream": true) the HTTP status is committed once the
first chunk is sent. A failure after that point cannot change the status, so it
arrives as a terminal SSE event and the stream then closes:
event: error
data: {"error":{"code":"upstream_error","message":"...","type":"routeur_error"},"request_id":"01K..."}
A failure before the first chunk (auth, routing, output-moderation block on a moderated org, or an upstream that produced no bytes) is returned as the ordinary JSON error above with its normal status code — no stream is opened.
Two stream-specific cases to handle client-side:
- Mid-stream
errorevent. Treat it like the equivalent HTTP error code:upstream_erroris retryable, a moderation block is not. - Truncated stream (no terminal
errorand no[DONE]). A deploy or scale-in can cut a long-lived stream. This is expected operationally; retry the request idempotently.
Retry guidance
- Retry:
429,502,504with exponential backoff; a mid-streamupstream_errorevent; a truncated stream. - Do not retry:
400,401,403. The request will keep failing.