Error Reference

Nodius returns errors via HTTP status codes and JSON-RPC error objects. This guide covers all error conditions, their meanings, and how to handle them.

Important โ€” numeric code collisions: Nodius proxy error codes and upstream Solana node error codes share the same numeric range (-32001 through -32015). This is an inherent consequence of JSON-RPC 2.0's server error code range and cannot be avoided without breaking compatibility with Solana RPC clients. A numeric code alone is not sufficient to determine the error source. SDKs and automated systems must use the combination of HTTP status code + numeric code + error message to disambiguate. The Proxy Error Codes table below separates proxy-generated codes from upstream Solana codes to make this explicit.

Proxy Error Codes (JSON-RPC)

Proxy error constants are stable and will not change without versioned deprecation. These are returned in the JSON-RPC error object or as HTTP error responses.

Code HTTP Constant Credits consumed? Retry? Retry delay SDK error class
-32010 402 INSUFFICIENT_CREDITS No After deposit โ€” InsufficientCreditsError
-32002 402 PAYMENT_REQUIRED No After deposit โ€” InsufficientCreditsError
-32005 429 RATE_LIMITED No Yes Retry-After header (โ‰ฅ1s) RateLimitError
-32005 429 CONCURRENCY_LIMITED No Yes 1s + jitter RateLimitError
-32003 502 BACKEND_UNAVAILABLE No Yes 2s + exp. backoff BackendUnavailableError
-32003 503 SERVICE_TEMPORARILY_UNAVAILABLE No Yes 5s + exp. backoff BackendUnavailableError
-32001 403 METHOD_NOT_ALLOWED No No โ€” MethodNotAllowedError
-32004 200 SERVICE_PROFILE_DISABLED No No โ€” ServiceProfileDisabledError
โ€” 403 NONCE_REUSED No No (regenerate nonce) โ€” AuthenticationError
โ€” 401 AUTH_FAILED No No (fix credentials) โ€” AuthenticationError / ExpiredSessionError
โ€” 400 INVALID_REQUEST No No (fix request) โ€” NodiusError
-32601 200 METHOD_NOT_FOUND No No โ€” MethodNotAllowedError / RpcError
-32602 200 INVALID_PARAMS No No (fix params) โ€” RpcError
-32603 200 INTERNAL_ERROR No Yes 1s + backoff RpcError

Note: -32005 is used for both rate limiting and concurrency limiting. Distinguish by the error message text: "rate limit exceeded" vs "concurrency limit exceeded". -32003 is used for both 502 (backend unreachable) and 503 (transient unavailability); distinguish by HTTP status code.

Why some JSON-RPC failures return HTTP 200

JSON-RPC 2.0 is a transport-agnostic protocol that communicates success and failure inside the response body (result vs error), not via HTTP status. When the proxy successfully processes a request and the upstream Solana node returns a JSON-RPC error (e.g., "method not found", "block not available"), the proxy delivers that error inside a 200 OK response โ€” the HTTP layer succeeded, even though the RPC call failed. Proxy-level errors that prevent the request from reaching the node (auth failure, no credits, rate limit) use appropriate HTTP status codes (401, 402, 429). The one exception is SERVICE_PROFILE_DISABLED: it returns HTTP 200 because the proxy deliberately rejected the call before billing, and the response is a valid JSON-RPC error object.

SDK recommendation: Both SDKs expose typed error classes that encapsulate the disambiguation logic. SDK consumers should catch typed exceptions rather than parsing numeric codes or message text directly.

HTTP Status Codes

200 OK

Request succeeded. The response body contains the JSON-RPC result. Note that a 200 status can still contain a JSON-RPC error (e.g., method not found) โ€” always check the error field in the response.

400 Bad Request

The request body is malformed or missing required fields.

{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Request body must be valid JSON"
  }
}

Common causes: - Invalid JSON syntax - Missing jsonrpc, method, or id fields - Invalid method parameters - Batch size exceeds maximum (20)

401 Unauthorized

Authentication failed.

{
  "error": {
    "code": "AUTH_FAILED",
    "message": "Invalid signature"
  }
}

Common causes: - Missing authentication headers - Invalid Ed25519 signature - Timestamp outside +-60 second window - Expired session token - Malformed public key

Troubleshooting: - Verify your system clock is synchronized (use NTP) - Ensure you're signing the correct payload format: solana-nodius:v2:{method}:{path}:{timestamp}:{nonce}:{body_hash}. - Check that the body hash matches the actual request body - Verify the signed path is the URL path only, without query string.

402 Payment Required

No credits available โ€” either your pubkey has no account record yet, or your balance is zero.

When no account record exists (no deposit has landed and POST /account/api-key was never called), the response includes deposit instructions:

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32002,
    "message": "payment required: deposit USDC to activate your account",
    "data": {
      "deposit_address": "CQKviPv5QupKhE6MuhSuqP4uh1JfrL93nxtcx23tLMRk",
      "usdc_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "minimum_deposit_usdc": "0.01",
      "network": "solana-mainnet",
      "instructions": "Send USDC (minimum $0.01) to the deposit address from your wallet. Your account is created automatically when the deposit confirms."
    }
  }
}
Field Value
Token USDC (SPL)
Chain Solana mainnet
USDC mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Deposit address CQKviPv5QupKhE6MuhSuqP4uh1JfrL93nxtcx23tLMRk
Minimum deposit $0.01 USDC

โš ๏ธ Do not send SOL or any token other than USDC. Only SPL USDC transfers are credited. Other tokens sent to the deposit address are permanently lost.

When the account record exists but the balance is zero or depleted:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32010,
    "message": "insufficient credits"
  }
}

Resolution: Send USDC (SPL, minimum $0.01) on Solana mainnet to the deposit address from your wallet. Credits appear within ~30 seconds of on-chain confirmation. Check your balance via GET /account/info. With x402 auto-pay enabled in the SDK, the 402 triggers an automatic micro-deposit and the call is retried.

403 Forbidden

The request is authenticated but not authorized.

{
  "error": {
    "code": "METHOD_NOT_ALLOWED",
    "message": "method not allowed: requestAirdrop"
  }
}

Common causes: - Replayed nonce (same nonce used within 60-second window) - Calling a denied method (requestAirdrop) - Account suspended

{
  "error": {
    "code": "NONCE_REUSED",
    "message": "Nonce has already been used"
  }
}

404 Not Found

Account or resource not found.

{
  "error": {
    "code": "ACCOUNT_NOT_FOUND",
    "message": "No account found for pubkey. Deposit USDC or call POST /account/api-key"
  }
}

429 Too Many Requests

Rate limit exceeded.

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Retry after 1 second."
  }
}

Headers:

Retry-After: 1
X-Ratelimit-Limit: 50
X-Ratelimit-Remaining: 0
X-Ratelimit-Reset: 1712000001

Resolution: Wait for the duration specified in Retry-After before retrying. Implement exponential backoff for repeated 429s.

500 Internal Server Error

Something went wrong on the server.

{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Internal server error",
    "requestId": "req_abc123"
  }
}

Resolution: Retry with backoff. If the issue persists, contact support with the requestId.

502 Bad Gateway

The upstream Solana node is unreachable.

{
  "error": {
    "code": "UPSTREAM_ERROR",
    "message": "Solana node unavailable"
  }
}

Resolution: Retry after a brief delay. Check /health for node status.

503 Service Unavailable

The service is temporarily unavailable. This can happen during startup, upstream failure, overload, accounting dependency failure, or critical disk pressure. Transient service-gate denials happen before billing and include a retry hint when available.

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32003,
    "message": "hot_rpc service temporarily unavailable due to critical disk pressure"
  }
}

Resolution: Retry with exponential backoff. Check nodius.xyz/status.

504 Gateway Timeout

The request exceeded its method-dependent timeout. See Request Timeouts for details.


Response Headers

All authenticated responses (including errors) include:

Header Description
X-Credits-Remaining Current credit balance after this request
X-Credits-Low Present and set to "true" when balance < 1000
X-Request-Id Unique identifier for debugging

Rate limit responses (429) include:

Header Description
Retry-After Seconds to wait before retrying
X-Ratelimit-Limit Maximum requests per second for this account
X-Ratelimit-Remaining Remaining requests in current window
X-Ratelimit-Reset Unix timestamp when the rate limit resets

Rate-limit headers (X-Ratelimit-*) are also present on non-429 authenticated responses. Public endpoints (/health, /pricing, /capabilities) do not include any of these headers.


JSON-RPC Error Codes

These errors are returned inside a 200 OK response, in the JSON-RPC error field. They originate from the Solana node or the proxy's JSON-RPC handling.

Standard JSON-RPC Error Codes

Code Description
-32700 Parse error: invalid JSON
-32600 Invalid request: missing required fields
-32601 Method not found
-32602 Invalid params
-32603 Internal error

-32700: Parse Error

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32700,
    "message": "Parse error: invalid JSON"
  }
}

The request body is not valid JSON.

-32600: Invalid Request

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32600,
    "message": "Invalid request: missing 'method' field"
  }
}

The JSON is valid but doesn't conform to the JSON-RPC 2.0 specification.

-32601: Method Not Found

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32601,
    "message": "Method not found: getInvalidMethod"
  }
}

The requested method is not supported. Check the API Reference for supported methods.

-32602: Invalid Params

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "Invalid params: expected base58 pubkey"
  }
}

Method parameters are invalid. Check the Solana JSON-RPC documentation for the correct parameter format.

-32603: Internal Error

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32603,
    "message": "Internal error"
  }
}

An unexpected error occurred in the RPC handler.

-32000 to -32099: Server Errors

Solana-specific errors that pass through from the upstream Agave node:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32002,
    "message": "Transaction simulation failed: Blockhash not found"
  }
}

Upstream Solana node error codes:

Code Typical Message Description
-32001 Node is behind by X slots Node is not caught up
-32002 Transaction simulation failed Transaction would fail
-32003 Transaction signature verification failure Bad transaction signature
-32004 Block not available Requested block has been purged from the node's ledger
-32005 Node is unhealthy Node health check failed
-32006 No snapshot available Snapshot not available
-32007 Long-running operation Request timed out on the node
-32009 Slot was skipped Requested slot has no block
-32014 Minimum slot not reached Slot not yet reached
-32015 Unsupported transaction version Version incompatibility

Distinguishing proxy errors from Solana errors: The same numeric code can come from either source. Use the HTTP status code and error constant to disambiguate:


Request Timeouts

Requests have method-dependent timeouts:

Category Timeout Examples
READ_CHEAP 5 seconds getSlot, getBalance, getAccountInfo
READ_MEDIUM 15 seconds getTransaction, simulateTransaction
READ_HEAVY / ARCHIVE 30 seconds Heavy indexed/archive endpoints when enabled
SEND 10 seconds sendTransaction
SEND_BUNDLE 10 seconds sendBundle

If a request exceeds its timeout, the proxy returns a 504 Gateway Timeout or a JSON-RPC error with code -32007.


WebSocket Error Codes

Close Codes

Code Reason Description Action
1000 normal Clean close by client No action
1008 policy_violation Invalid or expired token Re-authenticate
4001 auth_failed WebSocket authentication failed Check credentials
4002 insufficient_credits Credit balance below minimum (10) Deposit more USDC
4003 rate_limited Too many messages per second Reduce message rate
1006 abnormal Network interruption Reconnect with backoff

Subscription Errors

Returned as JSON-RPC error messages on the WebSocket:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32000,
    "message": "Subscription limit reached (100/100)"
  }
}
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32601,
    "message": "method not allowed: requestAirdrop"
  }
}

Common Troubleshooting

"Invalid signature" on every request

  1. Check your clock: Your system time must be within ยฑ60 seconds of UTC. Run ntpdate or check your NTP configuration.
  2. Verify the signing payload: Use solana-nodius:v2:{method}:{path}:{timestamp}:{nonce}:{body_hash}. The body hash is SHA-256 of the raw request body string.
  3. Ensure you're signing with the correct key: The public key in X-Pubkey must correspond to the private key used for signing.
  4. Check encoding: The signature should be base58-encoded. The public key should be base58-encoded.
  5. Check the path: Sign the URL path only, without query string.

"Account not found" after creating keypair

Your pubkey has no account record yet. Either: 1. Send USDC (SPL) on Solana mainnet to the deposit address (CQKviPv5QupKhE6MuhSuqP4uh1JfrL93nxtcx23tLMRk, min $0.01) โ€” credits appear within seconds and the record is created automatically. 2. Or call POST /account/api-key with wallet sig to create the record (zero balance) and get an API key.

await rpc.generateApiKey();

"Insufficient credits" but I sent a deposit

Rate limited despite low request volume

WebSocket keeps disconnecting

Service-gate error for archive methods

The hot-node endpoint is optimized for low-latency bots. Archive-only methods such as getEnrichedTransaction, explainTransaction, and getConfirmedTransaction are enabled on dedicated endpoint profiles. When a profile is disabled, the RPC response uses -32004 and no credits are consumed. Methods like getTransaction and getSignaturesForAddress are served by the hot node directly; if the transaction is too old, the upstream node returns its own descriptive error.

Requests timing out

Timeouts vary by method category:

If requests consistently time out, the Solana node may be under load โ€” check /health.