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
| Category | Where it appears | Meaning | What the caller should do |
|---|---|---|---|
validation | SDK + MCP | Bad input — address format, missing field, invalid amount | Fix the input and retry |
upstream | SDK + MCP | Backend API or RPC failure, possibly transient | Retry with exponential backoff |
flow | MCP only | Prerequisite missing — wallet not created, signing passphrase not set | Execute the requiredAction first, then retry |
auth | SDK + MCP | API key invalid, missing, or unauthorized | Stop — tell the user to configure credentials |
limit | SDK + MCP | Rate or quota exceeded | Back off, retry after the rate limit window |
not_available | SDK + MCP | Feature not enabled for this API key | Inform the user the feature is not on their plan |
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 (MPC signing layer, policy engine, Zod pre-validation, tool dispatch). Not returned by the REST API — SDK callers do not encounter these.
Validation Errors
| Code | Source | When It Happens |
|---|---|---|
INVALID_ADDRESS | MCP | Address fails Zod format check for the specified chain (e.g., not 0x-prefixed for EVM) — raised before the API call |
INVALID_AMOUNT | MCP | Human-readable amount is not a positive decimal string |
INVALID_AMOUNT_WEI | MCP | Wei amount is not a positive integer string |
MISSING_TOKEN_CONTRACT | MCP | Token transfer attempted with a symbol but no contract address — use resolve_asset first |
INVALID_PARAMS | MCP | Zod schema validation failed on tool input |
BAD_REQUEST | API | Backend returned 400 — check the request parameters |
NOT_FOUND | API | Backend returned 404 — the resource does not exist |
Flow Errors — MCP only
Flow errors signal prerequisites missing in the MPC signing layer, policy engine, or MCP environment. They are raised by MCP orchestration and never returned by the REST API, so SDK callers do not encounter them.| Code | When It Happens | Required Action |
|---|---|---|
WALLET_ALREADY_EXISTS | create_wallet called with a name that already exists locally | Choose a different walletName, or delete the existing wallet first |
PASSPHRASE_NOT_SET | create_wallet called without the signing passphrase configured | Set the WALLETSUITE_PASSPHRASE secret, then retry |
WRONG_PASSPHRASE | The configured passphrase cannot unlock the local share | Update WALLETSUITE_PASSPHRASE to match the passphrase used when this wallet was created |
MPC_OWNER_MODE_REQUIRED | An owner-only tool (create_wallet, create_custom_policy, or create_agent_api_key) called while not in owner mode | Restart the MCP server with MPC_AUTH_MODE=owner, then retry |
MISSING_POLICY_GUARDRAIL | create_custom_policy called with no constraint supplied | Supply at least one of allowlist, maxValueEth, or rateLimitPerHour, then retry |
MOONPAY_CONFIG_REQUIRED | prepare_onramp called without MoonPay env vars | Set MOONPAY_API_KEY and MOONPAY_SECRET_KEY |
Auth Errors
| Code | Source | When It Happens |
|---|---|---|
UNAUTHORIZED | API | API key is missing or invalid (backend returned 401) |
FORBIDDEN | API | API key is valid but not authorized for this operation (backend returned 403) |
Upstream Errors
| Code | Source | When It Happens |
|---|---|---|
SERVER_ERROR | API | Backend returned 500, 502, or 503 |
TIMEOUT | API | Request exceeded the timeout (default 60s) |
NETWORK | API | DNS or connection failure |
TX_COMPILER_* | API | Transaction compilation failed at the backend |
SIMULATION_FAILED | API | Transaction simulation at the backend failed |
INVALID_BACKEND_RESPONSE | MCP | Backend response did not match the expected schema (MCP client-side guard) |
Limit and Feature Errors
| Code | Source | When It Happens |
|---|---|---|
RATE_LIMITED | API | Backend returned 429 — too many requests |
PLAN_RESTRICTED | API | Backend returned 403 — feature not enabled on your API key |
FEATURE_GATED | MCP | MCP tool classified as not-available for your plan (surfaces PLAN_RESTRICTED to the agent as a not_available category error) |
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 only see the API-source categories: validation (from the backend, not Zod), auth, upstream, limit, and not_available. The flow category is MCP-only and will 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.