Error Handling
Structured JSON errors, streaming error events, and support correlation IDs.
Request correlation
Every response should include X-LK-Request-ID. Log it with failures when opening support tickets or tracing logs.
Typed JSON errors
Gateway failures return a structured JSON envelope with stable machine-readable codes:
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"category": "billing",
"message": "Insufficient credits for Platform Access. Please top up your balance.",
"request_id": "req_abc123",
"retryable": false
}
}| Field | Description |
|---|---|
error.code | Stable programmatic code |
error.category | Broad handling category such as upstream, model_output, auth, or billing |
error.message | Human-readable detail |
error.request_id | Correlation ID for request logs and support |
error.retryable | Whether retrying the same request can reasonably succeed |
Top-level code, message, and request_id remain for older SDKs. New integrations should use error.code and error.category.
Common codes
| HTTP | Code | Meaning |
|---|---|---|
401 | INVALID_API_KEY | Fix Authorization header |
400 / 422 | VALIDATION_ERROR | Fix request body |
403 | POLICY_REJECTED | Policy guardrail or route eligibility rejected input |
402 | INSUFFICIENT_CREDITS | Credits or plan limit |
429 | RATE_LIMITED | Retry after the Retry-After header (always present on 429) |
413 | REQUEST_TOO_LARGE | Request body exceeds the edge/app limit; reduce payload size |
413 | AUDIO_TOO_LARGE | Audio exceeds the audio byte budget; use audio.url or async jobs |
409 | IDEMPOTENCY_KEY_REUSED | Same Idempotency-Key with a different payload |
409 | IDEMPOTENCY_REPLAY_IN_PROGRESS | Original request still running; retry shortly |
503 | NO_HEALTHY_PROVIDER | See below — check retryable before backing off |
200 / 503 | TOOL_CALL_NOT_PRODUCED | A tool call was required, but the model returned text |
NO_HEALTHY_PROVIDER: configuration vs. transient
A 503 NO_HEALTHY_PROVIDER distinguishes two very different situations — branch on
error.retryable:
retryable: false+suggested_action: "attach_provider_for_capability"— a configuration state: no provider/route is attached for the required capability. No amount of client retrying fixes this; open the routing policy in the console (the error'sdetail.dashboard_url_pathpoints there) and attach a provider.retryable: true— providers are attached but currently unhealthy; retry with backoff.
Non-JSON responses never reach you
The API host speaks JSON on every response, including infrastructure failures: the
edge normalizes any non-JSON error (proxy error pages, origin-down responses) into
this same envelope, and an external synthetic monitor asserts it continuously. If you
ever observe an HTML error body from ai.latentkit.com, treat it as a platform bug
and report it with the X-LK-Request-ID.
Streaming errors
After SSE starts, terminal failures use:
event: error
data: {"error":{"code":"UPSTREAM_ERROR","category":"upstream","message":"...","request_id":"req_abc123","retryable":true},"code":"UPSTREAM_ERROR"}Client guidance
- Read
error.categoryfor generic handling anderror.codefor precise handling - Retry idempotent requests on transient
5xxwith backoff - Do not retry
401,400, or budget errors without changing inputs or billing state
Upgrade-oriented errors
Some plan-limit responses include fields like upgrade_required and upgrade_to for console-native upgrade flows.
See Error reference for the complete taxonomy and retry guidance.