Error Handling
When a run fails, @threadplane/chat surfaces a structured AgentError on the agent's error signal instead of a bare Error. It carries a machine-readable failure kind, a retryable flag, an optional HTTP status, and the original cause โ so you can render cause-specific copy, decide whether to offer a retry, and keep the raw error for telemetry.
<chat> already renders the built-in <chat-error> primitive, which shows legible per-kind copy and a Retry button for retryable failures. You only need this guide when you want custom error UI.
#The AgentError shape
agent.error() returns an AgentError | undefined. AgentError extends Error, so existing .message / instanceof Error reads keep working:
#Failure kinds
kind | Cause | retryable |
|---|---|---|
connection | Offline / DNS / connection refused / fetch failed | true |
auth | 401 / 403 โ credentials or API key are wrong | false |
server | 5xx (retryable) or a non-auth 4xx like 400/404/429 (not retryable) | varies |
interrupted | The stream closed mid-response after a run had started | true |
aborted | The user pressed stop โ treated as a graceful idle, not surfaced as an error | false |
The retryable flag is the value to branch on for UI: connection, server (5xx), and interrupted are retryable; auth, aborted, and non-auth 4xx are not.
#Reading the error
agent.retry() re-runs the last request and clears error. It's a no-op when a run is in flight or there is nothing to retry.
#The built-in error UI
<chat> auto-renders <chat-error>, which reads the agent's error and shows the message plus a Retry button when error.retryable is true:
The Retry button calls agent().retry() for you. For non-retryable failures (e.g. auth), no button is shown โ retrying the same bad credential would just fail again.
#Custom error UI
Read agent.error() directly to render your own surface. Override the default copy by mapping error.kind to your own strings โ AGENT_ERROR_MESSAGES holds the built-in defaults:
extractErrorMessage(value) is also exported for coercing any unknown error value into a readable string when you render an error outside <chat-error>.
#Classifying errors in a custom backend
Runtime adapters normalize raw failures through toAgentError() before setting agent.error(). If you write a custom adapter, call it too โ or throw an AgentError directly:
isAbortError(raw) is the shared predicate both adapters and toAgentError() use to recognize a user-requested stop (AbortError) so it settles to idle rather than surfacing as an error.
#API reference
| Export | Purpose |
|---|---|
AgentError | Structured error class on agent.error() (kind, retryable, status?, cause) |
AgentErrorKind | Union of the five failure classes |
AGENT_ERROR_MESSAGES | Default human-facing copy per kind |
toAgentError(raw) | Classify any raw value into an AgentError (idempotent) |
isAbortError(raw) | Predicate: is this a user-requested stop? |
ChatErrorComponent | The <chat-error> primitive (message + conditional Retry) |
extractErrorMessage(value) | Coerce any error value into a readable string |