Skip to content
Skip to content

Error Codes

Every Balchemy API error returns a predictable JSON envelope with a status code, message, and optional code field. This page documents the error format, all relevant HTTP status codes, and common error scenarios by domain.


Error envelope format

REST API errors

All REST errors return a consistent JSON body:

{
  "statusCode": 401,
  "message": "Unauthorized",
  "error": "Unauthorized"
}

For validation errors, the message field is an array of strings:

{
  "statusCode": 400,
  "message": ["message must be a string", "message should not be empty"],
  "error": "Bad Request"
}

For domain-specific service exceptions, an additional code field is included:

{
  "statusCode": 503,
  "message": "LLM provider unavailable",
  "code": "LLM_PROVIDER_UNAVAILABLE",
  "error": "Service Unavailable"
}

MCP (JSON-RPC) errors

MCP tool calls use the JSON-RPC 2.0 error format:

{
  "jsonrpc": "2.0",
  "id": "req-uuid",
  "error": {
    "code": -32603,
    "message": "Tool execution failed: insufficient balance",
    "data": {
      "tool": "trading_solana_jupiter_swap",
      "reason": "INSUFFICIENT_BALANCE"
    }
  }
}

Standard JSON-RPC error codes used by the MCP layer:

JSON-RPC codeMeaning
-32700Parse error — malformed JSON body
-32600Invalid request — missing jsonrpc, method, or id
-32601Method not found — tool does not exist or is not exposed
-32602Invalid params — required parameter missing or wrong type
-32603Internal error — tool execution failed

HTTP status code reference

CodeNameWhen it occurs
200OKRequest succeeded. Response body contains data.
201CreatedResource created successfully (e.g. new bot, new API key).
400Bad RequestInvalid request body, missing required field, or parameter validation failure.
401UnauthorizedMissing Authorization header, expired token, invalid nonce, or wallet mismatch.
403ForbiddenValid token but insufficient scope, missing CSRF token, or domain validation failure.
404Not FoundResource does not exist or the authenticated user does not have access to it.
409ConflictDuplicate resource (e.g. agent already claimed, wallet already connected).
413Content Too LargeRequest body or LLM token limit exceeded.
422Unprocessable EntitySemantic validation failed — body is valid JSON but fields are logically invalid.
429Too Many RequestsRate limit exceeded. Includes X-RateLimit-* headers.
500Internal Server ErrorUnhandled exception in the server. Check Sentry for trace ID.
503Service UnavailableTrading engine down, LLM provider unreachable, or circuit breaker open.

Auth errors

ScenarioStatusMessageResolution
No Authorization header401UnauthorizedInclude Authorization: Bearer <token> on every authenticated request.
Expired session token401Token expiredCall POST /api/nest/auth/refresh with your refresh token.
Invalid nonce401Invalid or expired nonceRequest a fresh nonce with POST /api/nest/auth/nonce or POST /api/nest/auth/evm/nonce.
Nonce already used401Nonce already consumedEach nonce is single-use. Request a fresh one for each login attempt.
Wallet address mismatch401Wallet address does not match signed messageThe address in the request body must match the wallet that signed the SIWE message.
CSRF token missing403ForbiddenInclude X-CSRF-Token on all POST, PATCH, PUT, and DELETE requests. Fetch a token at GET /api/nest/auth/csrf.
CSRF token invalid403Invalid CSRF tokenCSRF tokens are bound to sessions. Fetch a fresh token after each login.
Insufficient scope (MCP)403Scope insufficient: required trade, got readOnboard with the required scope or request a step-up token. See Hub — Scopes.
Revoked token401Token has been revokedThe identity access token was revoked via POST /api/public/erc8004/onboarding/tokens/revoke. Re-onboard to get a new token.

Trading errors

ScenarioStatusMessageResolution
Trading disabled on botSoft error (200)"Trading bu bot icin kapali."Enable trading in Studio bot settings.
Trading service unavailableSoft error (200)"Trading servisi su anda kullanilamiyor."The Rust trading engine is not reachable. Wait and retry.
Insufficient balance400Insufficient balance for requested swap amountReduce the swap amount or fund the custodial wallet.
Slippage exceeded400Slippage tolerance exceededIncrease slippageBps or reduce the trade size.
Token not found404Token not found: <mint>Verify the mint address or contract address. Use trading_solana_jupiter_tokens_search to resolve.
Circuit breaker open503Circuit breaker open for provider: jupiterThe trading engine has tripped the circuit breaker on a provider due to repeated failures. Wait 60 seconds and retry.
Order approval required200 (pending)Order created with status: "pending_approval"Call trading_orders_approve with the returned order_id, or set autoApprove=true in your order profile.
Input mint constraint (Solana)400inputMint must be native SOL or USDC (P3 constraint)Swap only SOL or USDC as the input token on Solana.
Custodial wallet not provisioned400Custodial wallet required for this operationCall trading_wallet_custodial_ensure first to provision a custodial wallet.
Kill switch active503Trading kill switch is active for chain: solanaA platform-level kill switch is active. Trading is temporarily halted.

MCP errors

ScenarioStatus / CodeMessageResolution
Invalid MCP API key401UnauthorizedThe MCP key is missing, expired, or revoked. Rotate keys at POST /api/nest/bots/:botId/mcp/keys.
Tool not found (default mode)JSON-RPC -32601Method not foundThe tool is not exposed in default mode. Enable MCP_EXPOSE_GRANULAR_TOOLS or use an agent-level tool instead.
Tool not found (granular mode)JSON-RPC -32601Tool not found: <name>The tool name is misspelled or does not exist in the catalog. Check the Tool Catalog.
Missing required parameterJSON-RPC -32602INVALID_PARAMS: <field> is requiredInclude all required parameters documented for the tool.
Step-up required for manage scope403Step-up token required for manage scopeIssue a step-up token via POST /api/nest/bots/:botId/mcp/step-up and include it as X-Step-Up-Token.
Bot not found404Bot not foundThe publicId in the MCP endpoint URL does not match any bot.
MCP payload too large400Request entity too largeReduce the size of the arguments object in the tools/call payload.

Agent (ERC-8004) errors

ScenarioStatusMessageResolution
Agent already claimed409Agent already claimedEach agentId can only be claimed once. Use the existing binding or choose a different agentId.
Invalid identity token401Identity token validation failedThe ES256 JWT is malformed, expired, or signed with an unregistered key. Check token expiry and provider registration.
Unknown identity provider401Unknown identity provider: <provider>The provider value is not registered. Contact Balchemy to register your provider.
Scope denied at onboarding403Requested scope not availablemanage scope is never issued at onboarding time. Start with read or trade.
Token JTI already revoked400Token already revokedThe token was previously revoked. No action needed — the token is already invalid.

Service exception codes

These codes appear in the code field for server-side service exceptions:

CodeHTTP StatusDescription
AUTHENTICATION_FAILED401Session authentication failed.
AUTHORIZATION_FAILED403Valid session but operation not permitted.
TOKEN_VALIDATION_FAILED401JWT or API key validation error.
INVALID_CREDENTIALS401Signature verification failed.
VALIDATION_ERROR400Input validation failed.
RESOURCE_NOT_FOUND404Requested resource does not exist.
RESOURCE_CONFLICT409Operation would create a duplicate resource.
INTERNAL_SERVICE_ERROR500Unhandled internal exception.
LLM_PROVIDER_NOT_FOUND404No LLM provider configured for this bot.
LLM_PROVIDER_UNAVAILABLE503LLM provider returned an error or is unreachable.
LLM_CIRCUIT_BREAKER_OPEN503LLM circuit breaker is open due to repeated failures.
LLM_CONFIGURATION_ERROR500Misconfigured LLM provider settings.
LLM_RATE_LIMIT_EXCEEDED429LLM provider rate limit reached.
LLM_TOKEN_LIMIT_EXCEEDED413Prompt exceeded the LLM context window.

SDK error codes

The Agent SDK maps API errors to typed AgentSdkError codes:

SDK codeTrigger
auth_error401 response from the API
policy_error403 response (scope or CSRF)
rate_limit_error429 response
provider_auth_errorIdentity provider validation failure
network_errorNetwork timeout or connection refused
execution_errorTool execution returned an error result
invalid_responseEmpty or non-JSON-RPC response body
unknown_errorUnclassified error

Catch and inspect the code in your error handler:

import { AgentSdkError } from "@balchemy/agent-sdk";
 
try {
  const result = await mcp.agentExecute({ instruction: "..." });
} catch (err: unknown) {
  if (err instanceof AgentSdkError) {
    switch (err.code) {
      case "auth_error":
        // Re-onboard or refresh your MCP key
        break;
      case "rate_limit_error":
        // Back off — Retry-After header value is in err.details
        break;
      case "network_error":
        // Retry with exponential backoff
        break;
    }
  }
}

The SDK implements automatic retry with exponential backoff for network_error and rate_limit_error. It does not retry execution_error (tool logic errors are deterministic).


Connection lost. Retrying...