← All failure classessystem execution

Unhandled Tool Error

A tool returned an error the agent didn't handle. Primarily TRAIL system-execution. Includes cryptic agent-INFRASTRUCTURE errors (payments, on-chain, RPC, wallets, API) where the fix is non-obvious and the base model is often wrong — see subclasses.

Subclasses

x402_payment_error

x402 payment failed at the facilitator — insufficient_funds, kyt_risk_detected (403 terminal), or a settlement block-height/timeout error.

solana_ata_missing

Solana SPL transfer reverted because the destination/source USDC Associated Token Account (ATA) doesn't exist on-chain (also the cause behind x402 transaction_simulation_failed).

solana_blockhash_expired

Solana BlockhashNotFound — the recentBlockhash expired (~60-90s window) before the tx was submitted.

solana_compute_budget

Solana tx silently dropped for exceeding its compute-unit budget (dropped, not failed — set setComputeUnitLimit).

eip3009_nonce_or_window

EIP-3009 gasless USDC transfer reverted: reused random nonce, or validAfter/validBefore time-window violation.

rpc_rate_limited

RPC provider rate-limited (429 / -32005) or the node is behind the chain tip returning stale reads.

wallet_user_rejected

Wallet returned 4001 (user rejected) or -32002 (request already pending) — EIP-1193 provider signals, terminal not retryable.

api_auth_or_idempotency

API call failed on expired/underscoped token mid-run, or a non-idempotent retry after timeout caused a duplicate (double-charge).

airnode_attestation

AirnodeHub attested-data verification failed (signature didn't recover to the Airnode address) or a rate-limited resolve.

database_lock_or_pool

Postgres transient/pool failure - 40001 serialization or 40P01 deadlock (retry the txn), P2024/QueuePool timeout (a connection leak), 53300 too-many-connections (needs a pooler).

cctp_attestation

Circle CCTP bridge - attestation polled too early (pending_confirmations), a 404 that's not-a-failure (keep polling), wrong domain-id, or nonce-already-used.

token2022_program

SPL Token-2022 - IncorrectProgramId (Token vs Token-2022), transfer-fee needs TransferCheckedWithFee, transfer-hook extra-account-metas, or non-transferable.

phantom_provider

Phantom Solana provider - 4100 unauthorized (connect first), 4900 disconnected, or the -32603 deeplink that only works on mainnet.

container_oom

Container OOMKilled / exit-137 (cgroup SIGKILL - confirm Reason:OOMKilled, raise the limit / runtime heap knob), CrashLoopBackOff, or a JVM/Node heap-OOM.

cloud_teardown

AWS DependencyViolation - out-of-order infra teardown (delete children first) or a ResourceInUse/already-exists conflict.

crm_lock_or_partial

Salesforce UNABLE_TO_LOCK_ROW (serialize + sort by parent, don't retry) or a HubSpot/Salesforce partial-commit (read per-record results).

stripe_decline

A card decline (hard vs soft) or a Stripe Issuing spending-control/webhook-timeout authorization, or a cart total that jumped past the approved budget.

oauth_grant

OAuth invalid_grant (re-authenticate, you can't refresh out of it) or invalid_token/insufficient_scope/invalid_client.

tls_cert_or_dns

TLS cert expired (silent outage), incomplete served chain (serve the intermediate), SNI/hostname mismatch, or a DNS NXDOMAIN/SERVFAIL.

queue_rebalance_or_visibility

Kafka CommitFailedException (poll-interval exceeded, don't retry the commit), SQS visibility-timeout duplicate, or a gRPC status code.

ach_return

A NACHA ACH return (R01 insufficient / R02-R04 admin; R10/R29 unauthorized must NOT be retried) or a Plaid ITEM_LOGIN_REQUIRED needing Link update-mode.

commerce_throttle

Shopify GraphQL cost-based throttle (returned as HTTP 200) or an Amazon SP-API QuotaExceeded (read the rate-limit header).

signature_or_clock

AWS SigV4 RequestTimeTooSkewed (clock skew - fix NTP, not credentials), SignatureDoesNotMatch, or a JWT signature/alg/aud failure.

calendar_concurrency

A 412 ETag lost-update (re-fetch + re-apply) or a 410 Gone sync-token that needs a full re-sync (not an auth error).

travel_gds

A GDS booking failure — Amadeus segment-sell failure (34651, availability changed between search and book; re-price, don't retry the stale offer), a skipped mandatory Flight Offers Price step / trimmed raw offer (400 MANDATORY DATA MISSING), a Sabre concurrent-request throttle (ERR.2SG.GATEWAY.REQUEST_THROTTLED), or a Sabre session expiry (restart from reservation lookup, not a re-auth).

k8s-orchestration

A Kubernetes control-plane / workload-lifecycle failure — ImagePullBackOff/ErrImagePull (read the Pod event, not the status; it's a backoff STATE not a retry), an admission-webhook denial (terminal - fix the manifest/policy), FailedScheduling (read why each node was rejected), Evicted (node pressure, distinct from OOMKill), or CreateContainerConfigError (a missing ConfigMap/Secret, not an image or crash problem).

mesh

An Istio/Envoy service-mesh failure — the 503 is NOT the diagnosis, the Envoy response FLAG is: UF/UH (connection failure / no healthy upstream - often a port mismatch or mTLS conflict), UO (circuit breaker tripped - debug the proxy budget not the app), NR/DC (missing VirtualService route), or a gRPC UNAVAILABLE/DEADLINE_EXCEEDED that maps from an Envoy flag.

serverless

An AWS Lambda concurrency/scaling failure — TooManyRequestsException/Rate Exceeded (429) with two causes (rate throttle vs concurrency-ceiling), or a SILENT async throttle where the invoke returns 202 but the event is retried twice then DLQ'd (the failure is in the Throttles/DLQ metrics, not the response). 'Rate Exceeded' from the CLI is control-plane, a different problem from invocation throttling.

messaging-a2p

A Twilio/SMS delivery or A2P 10DLC compliance failure — 30007 (carrier-filtered), 30034 (unregistered 10DLC number), 30035 (still provisioning) are compliance/content, not transient (retrying the same message fails); and a queued/201 is NOT delivery (poll the status callback). Look-alike codes have opposite fixes: 30003 (transient) vs 30006 (landline, permanent); 21610 (unsubscribed) must never be re-sent.

healthcare-edi

An X12 healthcare-claim EDI failure — a clean 999 (syntax accepted) with a REJECTED 277CA means the file was valid but the claim failed payer edits (277CA acceptance is BEFORE adjudication; the 835 is the real answer). On the 835, the CAS group code decides who pays: CO = provider write-off (don't bill the patient), PR = bill the patient — getting it wrong is a compliance violation; a CR code reverses a prior payment.

iac-state

A Terraform/OpenTofu state-management failure — 'Error acquiring the state lock' (ConditionalCheckFailedException on S3+DynamoDB, or a GCS .tflock / Azure blob lease): DON'T blindly force-unlock - read the Lock Info Who/Created to tell a STALE lock (crashed CI) from a LIVE apply, because breaking a live lock corrupts state; never use -lock=false as a habit. Or state DRIFT ('Objects have changed outside of Terraform' / a plan that wants to destroy real resources / an interrupted apply): review the plan and reconcile (import / -refresh-only), don't blind-apply or you destroy/duplicate live infrastructure.

data-warehouse

A Snowflake/Databricks data-warehouse failure — a Delta Lake ConcurrentAppendException (SQLSTATE 2D521) that fires EVEN on disjoint partitions under WriteSerializable isolation (fix: partition filters / serialize writers, not blind retry), or a Snowflake warehouse that's SUSPENDED (resume it; a resource-monitor credit-quota suspend is intentional cost control) / a Snowpipe ON_ERROR=CONTINUE that silently skipped bad rows to an error table.

identity-kyc

An identity/KYC verification (Persona/Alloy/Socure) decision — REVIEW / pending_manual_review is a ROUTING decision (queue for a human, NOT a failure to retry); REJECT is terminal and re-submitting the same identity trips velocity/fraud rules and risks BLACKLISTING - read the reason codes, don't auto-retry (it's a compliance action, always human-gated). Distinct from x402's KYT (transaction screen).

ci-cd-github

A GitHub Actions failure — '403 Resource not accessible by integration' because the GITHUB_TOKEN is READ-ONLY by default (2023 hardening): add an explicit permissions: block with least-privilege scopes, not write-all. Fork-PR workflows get a read-only token and NO secrets (a security boundary). 'Waiting for a runner' = runs-on labels match no registered runner.

redis

A Redis failure — 'OOM command not allowed when used memory > maxmemory' is NOT a container OOMKill; it's Redis's maxmemory limit under the default noeviction policy (rejects writes, still serves reads = silent for reads; fix: eviction policy / TTLs / raise maxmemory, don't restart). Or a cluster redirect: MOVED (permanent, follow it — use a cluster-aware client, don't retry the same node), ASK (one-shot), CROSSSLOT (co-locate with hash tags), READONLY (reconnect to the new primary after failover).

elasticsearch

An Elasticsearch/OpenSearch failure — circuit_breaking_exception ('Data too large') is a MEMORY guard returned as HTTP 429 (looks like rate-limiting but isn't; reduce the query's memory, don't just retry or raise the limit into a real OOM crash), or search_phase_execution_exception ('all shards failed' — read the per-shard reason, usually a mapping/fielddata/aggregation issue), or a mapping explosion.

microsoft-graph

A Microsoft Graph / Entra failure — a 429 carries a MANDATORY Retry-After (honor it exactly; 429_AppResourceUnitDaily = a daily app quota); a 403 (Authorization_RequestDenied) is a CONSENT / permission problem, NOT throttling — retrying never fixes it, add the scope + admin-consent; newly-granted permissions propagate asynchronously (a 401 right after a grant may resolve in minutes).

graphql

A cost-based GraphQL API rate-limit (GitHub, Shopify, and other GraphQL APIs) — the trap is HTTP 200 with an errors array (type=RATE_LIMITED / code=THROTTLED), a 'false success' a status-only check swallows. Don't blind-retry: compute the wait from the leaky bucket (x-ratelimit-reset, or throttleStatus currentlyAvailable/restoreRate), reduce the query cost, and inspect userErrors on mutations. (Shopify-specific throttling also lives in the ecommerce family; the generic + GitHub GraphQL patterns are here.)

adtech-rtb

An OpenRTB bidding failure — a 204 No Content is the NORMAL no-bid signal, NOT an error (never retry an auction request); the nbr (no-bid reason) and ${AUCTION_LOSS} loss code explain low win-rate; win/billing fire via nurl/burl callbacks; the exchange enforces a sub-100ms deadline (a slow bidder is silently timed out with no error).

Research cross-reference

How this class maps to the two leading agent-failure taxonomies.

MAST

Fail to ask for clarification

TRAIL

Tool/API errors, Tool output misinterpretation

Catch this with Snapback

Send your agent's trace to the ingest endpoint. Snapback diagnoses it — including this class — and returns a structured verdict with the root cause and a concrete fix. Pre-flight screening is free; you only draw credit on a full diagnosis.

curl -X POST "https://ingest.snapback.sh/v1/traces" \
  -H "Authorization: Bearer vdk_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "trace_id": "run-42",
    "steps": [
      { "agent": "planner", "action": "...", "output": "..." },
      { "agent": "executor", "tool": "...", "error": "..." }
    ]
  }'

Get your ingest token when you create a source. Already emitting OpenTelemetry? Point your exporter at /v1/traces/otlp — no re-instrumentation. AI agents can call the same pipeline over MCP (diagnose_trace).

What comes back

Illustrative — your verdict is diagnosed from your actual trace.

{
  "failure_class": "unhandled_tool_error",
  "failed_at_step": 2,
  "failure_agent": "executor",
  "root_cause": "<the specific cause, inferred from your trace>",
  "fix_suggestion": "<a concrete, applicable fix>",
  "confidence": 0.9
}

Catch this failure automatically

Snapback watches your agents and diagnoses this class the moment it happens — with the specific trace, the likely cause, and the fix.

Start free