skip to content
Errors

SDK

Errors

OpenAI-compat type and code names as the gateway ships them. Official SDKs already know 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

/v1/chat/completions, /v1/completions, and /v1/responses. A stream’s in-band error object matches the buffered envelope.

StatustypecodeMeaning
401invalid_request_errorinvalid_api_keyMessage Incorrect API key provided. Header WWW-Authenticate: Bearer. All auth failures are this one 401.
402insufficient_allowanceinsufficient_quotaBilling is not set up, or the balance cannot cover the request's worst case. Stays 402; not remapped to 429.
402cost_ceiling_exceededstays typeThe per-request ceiling x-conifer-max-cost-nanousd refused the worst case. Stays 402.
429rate_limit_errorrate_limit_exceededHeader Retry-After: 1. No invented x-ratelimit-* remaining-quota figures.
404see bodymodel_not_foundparam model. The body does not echo the id. Close matches may list error.suggestions.
400invalid_request_errorcontext_length_exceededThe prompt is over the model's context window. Other 400s still name the problem in the body, including tools or a modality the model does not declare. Capability refusals stay 400; they are not remapped to 402 or 429.

Anthropic /v1/messages

Types were already industry-shaped and stay that way. Official Anthropic clients keep reading the same type names.

Request ids

request-id and x-request-id echo the same value as x-conifer-request-id.

What we do not do

All auth failures are one 401. 402 is billing or the spend ceiling, never a missing tool or modality. 429 is rate limit only. Capability mismatches stay 400 and name the problem. Upstream identity is not leaked: no OpenRouter provider metadata. Remaining quota is not invented 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 spend cap
{
  "error": {
    "type": "cost_ceiling_exceeded"
  }
}
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"
  }
}