Skip to main content
Every non-2xx response throws ApiError. There is exactly one shape, and it is a transcription of the server’s error envelope — the client adds no taxonomy of its own, so the two can never disagree. Besides the fallback for an error body that is not an envelope (internal_error), the client makes one more ApiError itself: a 2xx body it cannot read.

The ApiError class

number
The HTTP status, e.g. 404.
string
The error family from the envelope, e.g. not_found, invalid_request.
string
The specific machine code, e.g. validation_failed, subscription_required, insufficient_credits.
string | undefined
The offending field, when the server names one. This is what the CLI prints.
string
The server’s correlation id for this call — quote it in a bug report; it is the single most useful field.
string
The human-readable message from the envelope.

Catching

A response this SDK cannot read

A 2xx body that does not match the SDK’s schema (an SDK older or newer than the API) throws ResponseParseError, a subclass of ApiError. It has the real status (a 2xx), code: "internal_error", the requestId, and three more fields. Its status means the call landed: don’t forward it as an HTTP status, and don’t retry a write on it, or it runs twice. Check instanceof ResponseParseError before treating an ApiError as a refusal.
string
The call’s HTTP method.
string
The call’s path, e.g. /v1/agents/agt_….
ZodIssue[]
What did not match, field by field. The message names the first three.

What the client does not do

  • No retries. A caller that wants retries owns that decision — the CLI and the dashboard want different policies. A 429 or 5xx is thrown like any other error.
  • No code → status table. type and status are read off the response. The server owns that mapping; a second copy here would be a second taxonomy that could drift.

Errors worth planning for

The full catalogue lives in the API error reference.