DOCS / API REFERENCE / ERRORS
Errors
Every error response — from both /v1 and /management/v1 — uses the same envelope, deliberately shaped like OpenAI's error format for client compatibility:
json
Authorization: Bearer lattice_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmessagestring Human-readable. For unhandled/unexpected exceptions this is always replaced with the generic
"Internal server error" — internal error text and stack traces never reach the client. See Security. typestring A coarse OpenAI-style category, derived purely from the HTTP status — not a stable identifier on its own, prefer
code for programmatic handling. codestring | null A stable
LatticeErrorCode. null only for errors the gateway didn't classify (unexpected exceptions). type derivation
| HTTP status | type |
|---|---|
401 | authentication_error |
403 | permission_error |
404 | not_found_error |
429 | rate_limit_error |
>= 500 | upstream_error |
| anything else | invalid_request_error |
Every error code
code | Status | Meaning |
|---|---|---|
missing_api_key | 401 | No Authorization header, or it isn't Bearer <token>. |
invalid_api_key | 401 | The key doesn't match any active key, or (for application keys) the owning application is disabled. |
revoked_api_key | 401 | Reserved for explicit revocation-specific messaging. |
model_not_found | 404 | model matches no registry id or alias. |
model_not_permitted | 403 | The application's allowedModels list doesn't include the requested model. |
unsupported_parameter | 400 | Reserved for parameter-specific rejection messaging. |
invalid_request | 400 | Body failed JSON parsing or schema validation (strict — unknown fields included), or a query parameter (e.g. days, limit, offset, status) was out of range. |
quota_exceeded | 429 | The application's monthlyTokenQuota is exhausted. |
rate_limit_exceeded | 429 | The application's rateLimitPerMinute is exceeded for the current 60-second window. |
provider_error | 502 | A single-candidate dispatch failed, or an adapter was invoked with no resolvable credentials (should be unreachable given registry validation). |
all_providers_failed | 502 | Every candidate in the resolved provider chain failed. |
model_registry_invalid | — | Boot-time only — the process refuses to start with an invalid models.config.ts. Never returned to a client. |
invalid_env | — | Boot-time only — the process refuses to start with invalid/missing environment variables. Never returned to a client. |
not_found | 404 | A management API resource (application, API key) doesn't exist. |
internal_error | 500 | Reserved for explicitly classified internal failures. |
NOTE
Any exception that isn't explicitly thrown as one of the codes above still gets a response — status
500, type: "upstream_error" is not guaranteed, code: null, message: "Internal server error". Treat code: null as "unclassified failure, safe to retry with backoff," the same way you'd treat an unexpected 500 from any other API. Handling errors as a client
ts
type ProviderAdapter = {
id: ProviderId;
createChatCompletion(
request: ChatCompletionRequest,
ctx: ProviderRequestContext,
): Promise<ChatCompletionResponse>;
streamChatCompletion(
request: ChatCompletionRequest,
ctx: ProviderRequestContext,
): AsyncGenerator<ChatCompletionChunk, void, void>;
};
type ProviderRequestContext = {
apiKey?: string;
providerModel: string;
signal: AbortSignal;
};