The Tally SDK turns every non-2xx response into a typed exception you can catch and branch on. The shape is consistent across the surface: every error is an instance ofDocumentation Index
Fetch the complete documentation index at: https://docs.tallyforagents.com/llms.txt
Use this file to discover all available pages before exploring further.
TallyError (or a subclass), and carries type, message, code?, status, and details? fields.
Class hierarchy
TallyError is the catch-all base. Anything the server returns that the SDK doesn’t have a specific subclass for surfaces as a plain TallyError.
Error shape
Every error carries these fields:| Field | Type | Description |
|---|---|---|
type | string | The server’s structured error type — unauthenticated, validation_failed, etc. |
message | string | Human-readable description. Safe to log; doesn’t include user data. |
code | string | undefined | Specific failure mode within type. See Error codes for payments. |
status | number | HTTP status code. |
details | unknown | Server-provided structured context (often the failed Zod issues). |
The classes
AuthenticationError — 401 / 403
NotFoundError — 404
tly_test_ key looking for a live-mode agent gets a NotFoundError, not a forbidden, because the resource is genuinely invisible to the key’s scope.
Recovery: check the id, check the mode, log it, and surface “not found” in your UI as appropriate.
ValidationError — 400
err.details typically contains the structured Zod issue list. err.code carries a specific failure mode where applicable (amount_invalid, address_invalid).
Most policy-related errors on
payments.create() (per-tx max exceeded, daily cap exceeded, recipient not allowed, etc.) are returned as 403 forbidden from the server, which the SDK maps to AuthenticationError — not ValidationError. The naming is awkward; see Payments — Error codes for the full mapping.RateLimitError — 429
Retry-After hint (the SDK doesn’t surface this on the error object today; check err.details if present).
Recovery: exponential backoff. The pattern:
idempotency_key so retries are safe — see Payments.
ConflictError — 409
agents.delete() on an agent with active grants).
Recovery: don’t retry without changing the request.
TallyError (base)
TallyError. The most common cases are 5xx server errors (rare) and network failures bubbled up through fetch.
Recovery: depends on status. 5xx should be retried with exponential backoff. Network errors (status: 0) should be retried with idempotency keys.
Idiomatic catch
err.code second; let everything else propagate. Catching TallyError to silently swallow is almost always a bug.
Server error shape
If you’re curious what the SDK is parsing, every error response from Tally looks like this:makeError(payload, status) maps type → class — unauthenticated and forbidden both become AuthenticationError, not_found becomes NotFoundError, etc.
That mapping is in packages/sdk/src/errors.ts if you want to see the exact switch.