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) throwsResponseParseError, 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
429or5xxis thrown like any other error. - No code → status table.
typeandstatusare 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.