# zidane/errors

> The typed errors an agent run can throw, with the helpers that classify and convert provider failures.

Import: `import { … } from 'zidane/errors'`. Source: [src/errors-entry.ts](https://github.com/Tahul/zidane/blob/main/src/errors-entry.ts).

Use `zidane/errors` to branch on why a run failed without importing the whole package. `agent.run()` wraps provider failures in these classes, so you match on `instanceof` instead of parsing provider strings. The entry also holds `matchesContextExceeded()`, `toTypedError()`, `errorMessage()` and `OperationTimeoutError`. See [Errors](https://zidane.si/docs/errors.md) for retry and budget behavior. `AgentLengthResumeExhaustedError` and `describeProviderLimit()` come from the root `zidane` entry.

```ts
import { createAgent } from 'zidane'
import { AgentAbortedError, AgentBudgetExceededError, AgentContextExceededError } from 'zidane/errors'
import { basic } from 'zidane/presets'
import { anthropic } from 'zidane/providers/anthropic'

const agent = createAgent({ ...basic, provider: anthropic(), behavior: { maxCostUsd: 0.5 } })

try {
  await agent.run({ prompt: 'Refactor the largest file in this repo.' })
}
catch (err) {
  if (err instanceof AgentBudgetExceededError)
    console.error(`Hit the ${err.limit} cap at ${err.actualValue}`)
  else if (err instanceof AgentContextExceededError || err instanceof AgentAbortedError)
    console.error(err.message)
  else
    throw err
}
```

## Functions

### `errorMessage`

Function.

Extract a printable message from an unknown thrown value.

Standardizes the `err instanceof Error ? err.message : String(err)` idiom
that every `catch (err)` block was reaching for.

```ts
function errorMessage(err: unknown): string
```

**Parameters**

- `err` (`unknown`): Thrown value of any type.

**Returns** `string`

Source: [src/errors.ts:775](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L775)

### `matchesContextExceeded`

Function.

Return true when `message` matches any of the known "context window exceeded"
phrasings. Safe for `''` / non-strings (returns false).

```ts
function matchesContextExceeded(message: unknown): boolean
```

**Parameters**

- `message` (`unknown`): Error message, or any value. Non-string values never match.

**Returns** `boolean`

Source: [src/errors.ts:446](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L446)

### `toTypedError`

Function.

Convert a `ClassifiedError` + underlying cause into the matching typed error instance.

```ts
function toTypedError(
  classification: ClassifiedError,
  provider: string,
  cause: unknown,
): AgentAbortedError | AgentContextExceededError | AgentProviderError | AgentToolPairingError
```

**Parameters**

- `classification` (`ClassifiedError`): Classification returned by the provider.
- `provider` (`string`): Name of the provider that raised the error.
- `cause` (`unknown`): Original error, attached as the typed error's `cause`.

**Returns** `AgentAbortedError | AgentContextExceededError | AgentProviderError | AgentToolPairingError`

Source: [src/errors.ts:805](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L805)

## Classes

### `AgentAbortedError`

Class.

Thrown when a run is aborted by the consumer via `agent.abort()` or an external `AbortSignal`.

```ts
class AgentAbortedError extends Error
```

**Constructor**

```ts
new AgentAbortedError(message?: string, options?: { cause?: unknown })
```

Creates the error.

**Parameters**

- `message?` (`string`, default `'Agent run aborted'`): Error message. Defaults to `'Agent run aborted'`.
- `options?` (`{ cause?: unknown }`): Optional `cause`.

**Returns** `AgentAbortedError`

**Properties**

- `code` (`'aborted'`, readonly): Stable error code, always `'aborted'`.

Source: [src/errors.ts:192](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L192)

### `AgentAuthError`

Class.

Thrown when a credential cannot be resolved, refreshed or was refused:
carries the structured [`AuthFailure`](https://zidane.si/docs/reference/errors.md#AuthFailure) a surface needs to offer
"sign in again" for the exact provider and account.

```ts
class AgentAuthError extends Error
```

**Constructor**

```ts
new AgentAuthError(message: string, auth: AuthFailure, options?: { cause?: unknown })
```

Creates the error.

**Parameters**

- `message` (`string`): Error message, with guidance.
- `auth` (`AuthFailure`): Which sign-in failed and why.
- `options?` (`{ cause?: unknown }`): Optional `cause`.

**Returns** `AgentAuthError`

**Properties**

- `auth` (`AuthFailure`, readonly): Which sign-in failed and why.
- `code` (`'auth_failed'`, readonly): Stable error code, always `'auth_failed'`.

Source: [src/errors.ts:83](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L83)

### `AgentBudgetExceededError`

Class.

Thrown by the loop when a run's cumulative cost, token consumption, or
wall-clock elapsed time crosses a ceiling configured on
`AgentBehavior.maxCostUsd` / `AgentBehavior.maxTotalTokens` /
`AgentBehavior.maxWallMs`. Acts as a programmable circuit
breaker for unattended runs — without this, the only built-in safety net
is `AgentBehavior.maxTurns`, which doesn't bound a single very
expensive turn (large context, deep reasoning).

The breach is checked **after** each turn completes (post-`turn:after`),
so the run may exceed the budget by one turn's worth of usage before
tripping. Callers wanting a tighter pre-turn estimate should layer their
own check on top of the `usage` hook.

The harness treats this the same way as [`AgentAbortedError`](https://zidane.si/docs/reference/errors.md#AgentAbortedError): the
session run is finalized as `'aborted'`, persisted stats reflect what
was actually consumed, and the parent agent re-throws so a caller's
`try`/`catch` can branch on `err instanceof AgentBudgetExceededError`
without string-sniffing.

```ts
class AgentBudgetExceededError extends Error
```

**Constructor**

```ts
new AgentBudgetExceededError(
  options: { actualValue: number; cause?: unknown; limit: 'cost' | 'tokens' | 'wallClock'; limitValue: number },
)
```

Creates the error.

**Parameters**

- `options` (`{ actualValue: number; cause?: unknown; limit: 'cost' | 'tokens' | 'wallClock'; limitValue: number }`): The tripped `limit`, its `limitValue`, the `actualValue` at that moment, and an optional `cause`.

**Returns** `AgentBudgetExceededError`

**Properties**

- `actualValue` (`number`, readonly): Actual consumed value at the moment the cap was crossed (same units as `limitValue`).
- `code` (`'budget_exceeded'`, readonly): Stable error code, always `'budget_exceeded'`.
- `limit` (`'cost' | 'tokens' | 'wallClock'`, readonly): Which ceiling tripped. `'cost'` → `maxCostUsd`, `'tokens'` → `maxTotalTokens`, `'wallClock'` → `maxWallMs`.
- `limitValue` (`number`, readonly): The configured cap (USD for `cost`, total tokens for `tokens`, ms for `wallClock`).

Source: [src/errors.ts:228](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L228)

### `AgentContextExceededError`

Class.

Thrown when the model or provider signals that the context window was exceeded.
Downstream consumers should catch this, prune history, and retry.

```ts
class AgentContextExceededError extends Error
```

**Constructor**

```ts
new AgentContextExceededError(message: string, options: TypedErrorOptions)
```

Creates the error.

**Parameters**

- `message` (`string`): Error message.
- `options` (`TypedErrorOptions`): Provider name (required), plus optional `providerCode` and `cause`.

**Returns** `AgentContextExceededError`

**Properties**

- `code` (`'context_exceeded'`, readonly): Stable error code, always `'context_exceeded'`.
- `provider` (`string`, readonly): Name of the provider that raised the error.
- `providerCode?` (`string`, readonly): Upstream error code, when the provider surfaced one.

Source: [src/errors.ts:131](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L131)

### `AgentProviderError`

Class.

Thrown when the provider returns a non-context error (auth, rate limit, server error, etc.).
Catch-all for unclassified provider failures.

```ts
class AgentProviderError extends Error
```

**Constructor**

```ts
new AgentProviderError(message: string, options: TypedErrorOptions)
```

Creates the error.

**Parameters**

- `message` (`string`): Error message.
- `options` (`TypedErrorOptions`): Provider name (required), plus optional `providerCode`, `retryable`, `limit` and `cause`.

**Returns** `AgentProviderError`

**Properties**

- `code` (`'provider_error'`, readonly): Stable error code, always `'provider_error'`.
- `limit?` (`ProviderLimit`, readonly): The rate limit, spent quota or overload behind the error, when that is what it was.
- `provider` (`string`, readonly): Name of the provider that raised the error.
- `providerCode?` (`string`, readonly): Upstream error code, when the provider surfaced one.
- `retryable?` (`boolean`, readonly): Whether a retry with backoff is likely to succeed. See
  `ClassifiedError.retryable`. Absent when the provider did not
  classify the error — callers should treat absent as "don't retry".

Source: [src/errors.ts:157](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L157)

### `AgentToolNotAllowedError`

Class.

Describes a tool call blocked because the union of `allowed-tools` across the
active skills does not permit it. The gate builds it but never throws it.

Built by the allowed-tools gates registered on `tool:gate` and
`mcp:tool:gate`. The gate sets `block = true` and copies this error's
`message` into `reason`, so consumers that do not look at this typed error
still get a useful string.

```ts
class AgentToolNotAllowedError extends Error
```

**Constructor**

```ts
new AgentToolNotAllowedError(
  options: { activeSkills: readonly string[]; allowedUnion: readonly string[]; cause?: unknown; displayName: string; toolName: string },
)
```

Creates the error.

**Parameters**

- `options` (`{ activeSkills: readonly string[]; allowedUnion: readonly string[]; cause?: unknown; displayName: string; toolName: string }`): Tool names, the allowed-tools union, the active skill names, and an optional `cause`.

**Returns** `AgentToolNotAllowedError`

**Properties**

- `activeSkills` (`readonly string[]`, readonly): Names of the skills currently active when the block fired.
- `allowedUnion` (`readonly string[]`, readonly): Flattened union of `allowedTools` patterns across active skills.
- `code` (`'tool_not_allowed'`, readonly): Stable error code, always `'tool_not_allowed'`.
- `displayName` (`string`, readonly): Aliased / wire name the LLM saw.
- `toolName` (`string`, readonly): Canonical tool name the agent tried to call.

Source: [src/errors.ts:358](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L358)

### `AgentToolPairingError`

Class.

Thrown by the pre-send pairing repair when `AgentBehavior.strictToolPairing`
is `true` and [`ensureToolResultPairing`](https://zidane.si/docs/reference/index.md#ensureToolResultPairing) would otherwise patch over
corruption. Strict mode opts into fail-fast for training-data collectors and
any consumer that prefers to bail out rather than ship a transcript carrying
a [`SYNTHETIC_TOOL_RESULT_PLACEHOLDER`](https://zidane.si/docs/reference/index.md#SYNTHETIC_TOOL_RESULT_PLACEHOLDER).

The `repairs` field carries every repair the loop would have made — useful
for postmortems and for surfacing exactly which transcripts were rejected.

Note: callers consuming the chat layer (TUI/SDK presets) typically leave
`strictToolPairing` off so user-facing sessions auto-heal instead of
crashing.

```ts
class AgentToolPairingError extends Error
```

**Constructor**

```ts
new AgentToolPairingError(
  options: { cause?: unknown; message: string; provider?: string; providerCode?: string; repairs: readonly { callId?: string; messageIndex: number; mode: string }[] },
)
```

Creates the error.

**Parameters**

- `options` (`{ cause?: unknown; message: string; provider?: string; providerCode?: string; repairs: readonly { callId?: string; messageIndex: number; mode: string }[] }`): Message, optional `provider` and `providerCode`, the `repairs` list, and an optional `cause`.

**Returns** `AgentToolPairingError`

**Properties**

- `code` (`'tool_pairing_corruption'`, readonly): Stable error code, always `'tool_pairing_corruption'`.
- `provider?` (`string`, readonly): Provider whose wire format the corruption would have hit.
- `providerCode?` (`string`, readonly): Upstream error code when the corruption was detected from a 400 response.
- `repairs` (`readonly { callId?: string; messageIndex: number; mode: string }[]`, readonly): Repairs the harness would have performed had strict mode been off.
  Preserves the full diagnostic so consumers can route to telemetry,
  `/rewind` flows, or training-data quarantine without re-walking the
  transcript.

Source: [src/errors.ts:310](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L310)

### `OperationTimeoutError`

Class.

Error thrown when an operation exceeds its configured time limit.

```ts
class OperationTimeoutError extends Error
```

**Constructor**

```ts
new OperationTimeoutError(operation: string, timeoutMs: number, message?: string)
```

Creates an error for an operation that exceeded its time limit.

**Parameters**

- `operation` (`string`): Name of the operation that timed out.
- `timeoutMs` (`number`): Time limit that was exceeded, in milliseconds.
- `message?` (`string`): Custom message. Defaults to `<operation> timed out after <timeoutMs>ms`.

**Returns** `OperationTimeoutError`

**Properties**

- `code` (`'operation_timeout'`, readonly): Stable error code, always `'operation_timeout'`.
- `operation` (`string`, readonly): Name of the operation that timed out.
- `timeoutMs` (`number`, readonly): Time limit that was exceeded, in milliseconds.

Source: [src/timeout.ts:2](https://github.com/Tahul/zidane/blob/main/src/timeout.ts#L2)

## Constants

### `CONTEXT_EXCEEDED_MESSAGE_PATTERNS`

Constant.

Regex patterns matching common "context window exceeded" messages across providers.

Use [`matchesContextExceeded`](https://zidane.si/docs/reference/errors.md#matchesContextExceeded) to test a free-form error message against them.
Provider authors can also compose these into their own `classifyError` fallbacks.

```ts
const CONTEXT_EXCEEDED_MESSAGE_PATTERNS: readonly RegExp[]
```

Source: [src/errors.ts:411](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L411)

## Interfaces

### `AuthFailure`

Interface.

Which sign-in failed, enough for a surface to offer fixing it. JSON-safe: it is persisted with the run.

```ts
interface AuthFailure
```

**Properties**

- `accountId?` (`string`): Stable id of the account that failed, when the credential has one.
- `accountLabel?` (`string`): That account's name, when it has one.
- `holderPid?` (`number`): `busy`: the pid holding the refresh lock, when it is on this host.
- `kind` (`AuthFailureKind`): Why it failed.
- `provider` (`string`): The provider name as the provider calls itself (`anthropic`, `openai`), or the server / integration name.
- `providerId?` (`string`): Credentials key / OAuth flow id (`anthropic`, `openai-codex`), when it differs from nothing else; absent for a 401 the loop classified.
- `source` (`'provider' | 'mcp' | 'integration'`): What signs in: a model provider, an MCP server, an integration.

Source: [src/errors.ts:61](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L61)

### `ClassifiedError`

Interface.

Structured classification returned by `Provider.classifyError`

```ts
interface ClassifiedError
```

**Properties**

- `kind` (`ClassifiedErrorKind`): Category of the error.
- `limit?` (`ProviderLimit`): Set when the provider refused for a rate limit, a spent quota or overload; `message` is then [`describeProviderLimit`](https://zidane.si/docs/reference/index.md#describeProviderLimit)'s.
- `message?` (`string`): Optional human-readable message override. Falls back to the underlying error's message.
- `providerCode?` (`string`): Upstream error code as surfaced by the provider (e.g. `context_length_exceeded`). Optional.
- `retryable?` (`boolean`): Hint that the error is transient and a retry with backoff is reasonable
  (e.g. 429, 5xx, truncated stream). Omitted when the provider can't decide;
  callers should default to "do not retry" when absent to avoid hammering
  terminal failures (auth, invalid request).

Source: [src/errors.ts:16](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L16)

## Types

### `AuthFailureKind`

Type.

Why a sign-in stopped working:

- `expired`: the refresh failed for a reason that signing in again fixes.
- `revoked`: the grant was revoked or rejected (`invalid_grant`).
- `missing`: no credential is stored (or the pinned account is gone).
- `busy`: another process holds the refresh lock and has not let go.
- `network`: the refresh could not reach the provider; retrying may do.
- `rejected`: the provider refused the credential it was sent (a 401).

```ts
type AuthFailureKind =
  | 'expired'
  | 'revoked'
  | 'missing'
  | 'busy'
  | 'network'
  | 'rejected'
```

Source: [src/errors.ts:58](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L58)

### `ClassifiedErrorKind`

Type.

Kind of classified provider error

```ts
type ClassifiedErrorKind =
  | 'context_exceeded'
  | 'provider_error'
  | 'aborted'
  | 'tool_pairing_corruption'
```

Source: [src/errors.ts:13](https://github.com/Tahul/zidane/blob/main/src/errors.ts#L13)
