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
flow errors, a requiredAction is always included:
Error Categories
Common Error Codes
Every error carries acode. 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 statedenied 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. Thecategory field tells the agent what class of action to take; requiredAction (when present) gives a concrete next step.
A well-behaved agent should:
- Check
category - If
flow— execute therequiredAction, then retry the original request - If
validation— fix the input based on themessage, then retry - If
upstream— retry with exponential backoff (3 attempts, then surface to user) - If
auth— stop and ask the user to fix their credentials - If
limit— wait and retry - If
not_available— inform the user
From the SDK
SDK calls throw anApiError 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.
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. Aflow 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.