skip to content
Errors

SDK

Errors

The type and code names Conifer returns on the OpenAI-compat wire. The official SDKs already handle these names.

Catch the official client’s error class, then branch on status and code.

errors.ts
import OpenAI, { APIError } from "openai";

try {
  await client.chat.completions.create({ /* … */ });
} catch (err) {
  if (err instanceof APIError) {
    console.error(err.status, err.code, err.error);
  }
  throw err;
}
errors.py
from openai import APIError, AuthenticationError, NotFoundError, RateLimitError

try:
    client.chat.completions.create(...)
except AuthenticationError as e:
    print("401", e.code)
except NotFoundError as e:
    print("404", e.code, e.body)
except RateLimitError as e:
    print("429", e.code)
except APIError as e:
    print(e.status_code, e.code, e.body)

OpenAI-compat

These names apply on /v1/chat/completions, /v1/completions and /v1/responses. On a stream, the in-band error object has the same shape as the buffered envelope.

StatustypecodeMeaning
401invalid_request_errorinvalid_api_keyThe message is Incorrect API key provided and the header is WWW-Authenticate: Bearer. Every auth failure returns this one 401, whether the key is missing, mistyped, expired or revoked.
402insufficient_allowanceinsufficient_quotaBilling is not set up, or the balance cannot cover the request. Nothing is charged. It stays a 402 and is not remapped to 429.
402cost_ceiling_exceededstays typeThe request could have cost more than the ceiling you set in x-conifer-max-cost-nanousd. Nothing is charged.
402key_spend_cap_exceededstays typeThis key has reached its own spend cap. The account may be funded and other keys still work, so adding credit does nothing here. Rotate the key or raise its cap. The body names key_id, cap_nanodollars and would_charge_nanodollars, and spent_nanodollars when it is known. There is no code, so branch on type.
409request_in_progressstays typeThe same idempotency key was sent twice. If the message ends “retry shortly”, the first attempt is still finishing and a retry is safe; it cannot bill twice. “Already used with a different request body” means change the key or the body.
429rate_limit_errorrate_limit_exceededThe header is Retry-After: 1. Conifer does not send invented x-ratelimit-* figures.
404model_not_foundmodel_not_foundThe param is model. The id is not in the catalog your key can call. Close matches, if any, are listed in error.suggestions.
400invalid_request_errorcontext_length_exceededThe prompt is over the model's context window. Some providers report this themselves, and that relays as a 422 upstream_error naming the token counts. Other 400s also say what is wrong, for example tools sent to a model that does not declare them. Capability refusals stay 400 and are not remapped to 402 or 429.

Capability refusals

Some 400s come from asking a model for something it does not do, such as image content on a model without the vision cap or tools on a model without tools. A different model would serve the same request. The Conifer SDK types this as ConiferCapabilityError, the request is not billed, and the TypeScript fallback chain moves on to the next model.

Anthropic /v1/messages

Error types on this route follow Anthropic’s shape, so the official Anthropic clients read them unchanged.

Request ids

request-id and x-request-id carry the same value as x-conifer-request-id. Quote it when you write in about a request.

What each status means

Every auth failure is one 401. A 402 means billing or a spend ceiling, never a missing tool or modality. A 429 is rate limit only. Capability mismatches stay 400 and name the problem in the body. Responses carry no OpenRouter provider metadata and no invented remaining-quota figures on x-ratelimit-* headers.

Bodies

HTTP 401
{
  "error": {
    "message": "Incorrect API key provided",
    "type": "invalid_request_error",
    "code": "invalid_api_key"
  }
}
HTTP 402 billing
{
  "error": {
    "type": "insufficient_allowance",
    "code": "insufficient_quota",
    "docs_url": "https://conifer.build/console#/billing"
  }
}
HTTP 402 cost ceiling
{
  "error": {
    "type": "cost_ceiling_exceeded"
  }
}
HTTP 402 key spend cap
{
  "error": {
    "type": "key_spend_cap_exceeded",
    "key_id": "…",
    "cap_nanodollars": 5000000000,
    "spent_nanodollars": 4900000000,
    "would_charge_nanodollars": 200000000
  }
}
HTTP 429
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded"
  }
}
HTTP 404
{
  "error": {
    "code": "model_not_found",
    "param": "model"
  }
}
context length
{
  "error": {
    "type": "invalid_request_error",
    "code": "context_length_exceeded"
  }
}