Skip to main content
Every error from WalletSuite includes a category, code, and message. Errors in the flow category also include a requiredAction — a specific instruction for what the caller should do next. The contract is identical across the REST API, MCP tools, and the SDK — only the wrapper around it differs. Agents and integrators can recover programmatically instead of guessing.

Error Format

For flow errors, a requiredAction is always included:

Error Categories

Common Error Codes

Every error carries a code. The Source column tells you which layer raised it — and which surfaces can see it:
  • API — returned by the WalletSuite REST API. Visible to SDK and MCP callers alike.
  • MCP — raised by MCP tool orchestration (signing layer, policy engine, schema pre-validation, tool dispatch). Not returned by the REST API — SDK callers do not encounter these.

Validation Errors

Flow Errors — MCP only

Flow errors signal a missing prerequisite in the MCP signing flow — for example, a transfer that must be prepared before it can be signed. They are raised by MCP orchestration and never returned by the REST API, so SDK callers do not encounter them. (Policy denials are separate and reach every surface — see Policy Denials.) Policy denials are covered in Policy Denials below.

Auth Errors

Upstream Errors

Limit and Feature Errors

Policy Denials

The policy engine evaluates every signing intent on every surface — MCP, SDK, and REST. When your organization’s policy denies an intent, WalletSuite records it in state denied with a decision reason and a policyDecisionId, and no signature is produced. On MCP this arrives as a flow error whose message carries the decision reason and whose requiredAction tells the agent how to proceed; SDK and REST callers receive the same decision reason and policyDecisionId. A policy denial is deterministic. The same request denies again until the request or the policy changes, so do not blindly retry. Quote the policyDecisionId when raising a support ticket. See Policy Gates for the rule model and Policy Decisions for the decision record on every intent.

Consuming errors

The same structured payload reaches the caller through two different wrappers. Pick the sub-section that matches your surface.

From an AI agent (MCP)

Every MCP tool response surfaces the structured error verbatim. The category field tells the agent what class of action to take; requiredAction (when present) gives a concrete next step. A well-behaved agent should:
  1. Check category
  2. If flow — execute the requiredAction, then retry the original request
  3. If validation — fix the input based on the message, then retry
  4. If upstream — retry with exponential backoff (3 attempts, then surface to user)
  5. If auth — stop and ask the user to fix their credentials
  6. If limit — wait and retry
  7. If not_available — inform the user

From the SDK

SDK calls throw an ApiError wrapper. The structured payload lives in err.bodySnippet as a JSON string — parse it to reach category, code, and message. SDK callers see the API-source categories: validation (from the backend), auth, upstream, limit, and not_available — plus policy denials, which reach every surface with the decision reason and policyDecisionId. The flow category (MCP orchestration prerequisites) does not appear in SDK responses.
For SDK-specific wrapper fields (url, method, status, attempt) and debug-logging behavior, see SDK Error Handling.

Design Principle

Errors are designed so agents can recover without human intervention whenever possible. A flow error with a requiredAction gives the agent a concrete next step — it does not need to guess or ask the user for help. Internal error details (internalMessage) are logged server-side but never included in the response sent to the LLM. The agent sees only what it needs to act on.