# Errors

> HTTP, JSON-RPC, WebSocket and gRPC error codes, their causes and their fixes.

Source: https://docs.constant-k.com/rpc/errors/

Errors come from two places. The constant-k gateway checks your key and your limits before a request reaches a node, and answers with an HTTP error status such as `401` or `403`. The Solana node runs the method and answers with a JSON-RPC `error` object.

```json
{
  "jsonrpc": "2.0",
  "error": { "code": -32602, "message": "Invalid param: WrongSize" },
  "id": 1
}
```

Some errors also carry a `data` field with details, such as simulation logs.

## Gateway errors

The gateway answers with a JSON-RPC error body and `"id": null`, except the `getTokenLargestAccounts` concurrency `429`, which echoes the request `id`. Placeholders in angle brackets are filled in with the method, the category or the limit that was hit.

| HTTP status |   Code   | Message                                                                     | Cause and fix                                                                                                                                                                            |
| :---------: | :------: | :-------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|    `401`    | `-32600` | `Missing API key`                                                           | No key was sent. Add it to the URL or a header. See [Authentication](https://docs.constant-k.com/get-started/authentication/).                                                                                      |
|    `403`    | `-32600` | `Invalid API key`                                                           | The key is wrong or was re-rolled. Copy it again from My Account.                                                                                                                        |
|    `403`    | `-32600` | `<method> requires higher tier`                                             | The method is not on your plan, for example `getLatestBlockhash` on Free. Upgrade, or call a method your plan includes. See [Plans & Limits](https://docs.constant-k.com/get-started/plans-and-limits/).            |
|    `403`    | `-32600` | `<method> not supported`                                                    | The method is not served on any plan: `getLargestAccounts`, `sendBundle` and a few methods Solana has removed. Retrying will not help.                                                   |
|    `400`    | `-32600` | `Batch requests are not supported`                                          | The body is a JSON array. Send one call per request. Even a one-element array is rejected.                                                                                               |
|    `400`    | `-32600` | `<method> requests a maximum of 100 items (<N> requested)`                  | `getMultipleAccounts` and `getSignatureStatuses` take at most 100 items. Split the list.                                                                                                 |
|    `429`    | `-32005` | `Global rate limit exceeded (<N>/sec, batch of <B>)`                        | You went over your plan's total requests per second.                                                                                                                                     |
|    `429`    | `-32005` | `Rate limit exceeded (<category>: <N>/sec)`                                 | You went over the cap for that group of methods, such as heavy block and history calls.                                                                                                  |
|    `429`    | `-32005` | `Global <method> capacity reached (<N>/sec across all keys); retry shortly` | That method is at capacity for every key, not only yours. Retry shortly.                                                                                                                 |
|    `429`    | `-32005` | `getProgramAccounts concurrency limit reached (per-key); retry shortly`     | Your API key already has as many `getProgramAccounts` and `getProgramAccountsV2` calls in progress as its plan allows: 1 on Blade Runner, 3 on Nexus. Retry when one of them finishes.   |
|    `429`    | `-32005` | `Node is unhealthy`                                                         | Too many `getTokenLargestAccounts` requests were in progress at once, from your key or from all keys together, and this one could not start within 5 seconds. Retry after a short pause. |
|    `503`    | `-32005` | `getTokenLargestAccounts is temporarily unavailable; retry shortly`         | `getTokenLargestAccounts` is temporarily unavailable, or cannot be answered at the requested commitment at that moment. Retry shortly.                                                   |
|    `503`    | `-32000` | a congestion message ending `retry shortly`                                 | The region is shedding load. The response carries a `Retry-After` header. Wait that many seconds, then retry.                                                                            |

> **A rate-limit 429 carries no wait time:** Rate-limit responses (`-32005`) carry no `Retry-After` header and no `X-RateLimit-*` or `RateLimit-*` headers, so backoff is the client's own job. Budgets are counted in whole seconds and reset at the start of each new second, so a short wait is usually enough. See [How rate limits work](https://docs.constant-k.com/get-started/plans-and-limits/#rate-limits).

## Long-term storage responses

On Blade Runner and Nexus tier plans, [Cube Runner](https://docs.constant-k.com/cube-runner/#long-term-storage) retrieves a block from long-term storage when no cache, ledger or other region holds it. A `getBlock` request returns the block when it is retrieved within 25 seconds. Otherwise the response is HTTP `429` with a `Retry-After` header and code `-32019`, and it echoes the request `id`.

| HTTP status |   Code   | Message                                                                        | Cause and fix                                                                                                                                                                                                                                                                    |
| :---------: | :------: | :----------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|    `429`    | `-32019` | `Block <slot> is being retrieved from long-term storage; retry in <N> seconds` | The block is queued and stays queued. Wait `Retry-After` seconds, then send the same request again. See [Queued requests](https://docs.constant-k.com/cube-runner/#queued-requests).                                                                                                                        |
|    `429`    | `-32019` | A message stating the reason                                                   | The block was not queued, was dropped from the queue, or was not returned by long-term storage. `data.reason` names the cause: `queue_full`, `key_full`, `key_monthly`, `dropped` or `failed`. See [Responses that are not queued](https://docs.constant-k.com/cube-runner/#responses-that-are-not-queued). |

## Standard JSON-RPC errors

|   Code   | Message          | What it means                                                                            |
| :------: | :--------------- | :--------------------------------------------------------------------------------------- |
| `-32700` | Parse error      | The body is not valid JSON.                                                              |
| `-32600` | Invalid request  | The body is not a valid JSON-RPC 2.0 request.                                            |
| `-32601` | Method not found | The method name is wrong or does not exist. Method names are case sensitive.             |
| `-32602` | Invalid params   | A parameter is missing or has the wrong type or format, for example a malformed address. |
| `-32603` | Internal error   | The node failed while it handled the call. Retry with backoff.                           |

## Solana node errors

These codes come from the node software, as do their messages.

|   Code   | Meaning                                                                                                                                                                                                                             | What to do                                                                                                                                                       |
| :------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-32001` | Block not available. For `getBlock` on Free and Operator tier plans, no cache, ledger or other region holds the block. For other methods, the block is older than the region's ledger. The message gives the first available block. | Ask for a slot at or above that block. On Blade Runner and Nexus tier plans, [Cube Runner](https://docs.constant-k.com/cube-runner/) retrieves such a block from long-term storage instead. |
| `-32002` | Transaction simulation (preflight) failed. `data` holds the error and the logs.                                                                                                                                                     | Read `data.logs`, fix the transaction, then resend. See [Transaction errors](#transaction-errors).                                                               |
| `-32003` | Transaction signature verification failed.                                                                                                                                                                                          | Sign after the message is final, with every required signer.                                                                                                     |
| `-32004` | Block not available for this slot.                                                                                                                                                                                                  | The block may not be ready yet. Retry shortly.                                                                                                                   |
| `-32005` | Node is unhealthy or behind. `data` may show how many slots behind.                                                                                                                                                                 | Retry with backoff, or use another region.                                                                                                                       |
| `-32006` | Precompile verification failed (for example an Ed25519 or secp256k1 instruction).                                                                                                                                                   | Check the precompile instruction data.                                                                                                                           |
| `-32007` | The slot was skipped: no block was produced.                                                                                                                                                                                        | Normal on Solana. Move on to the next slot.                                                                                                                      |
| `-32008` | No snapshot is available.                                                                                                                                                                                                           | Retry later.                                                                                                                                                     |
| `-32009` | The slot was skipped, or is missing in long-term storage.                                                                                                                                                                           | Treat it as skipped.                                                                                                                                             |
| `-32010` | The key is excluded from the account secondary index, so this method is unavailable for it.                                                                                                                                         | Query this account another way, or [contact support](https://docs.constant-k.com/get-started/support/).                                                                                     |
| `-32011` | Transaction history is not available from this node.                                                                                                                                                                                | Retry, or contact support if it persists.                                                                                                                        |
| `-32012` | Scan error, for example when an account scan returns too much data.                                                                                                                                                                 | Add or tighten filters, and use `dataSlice`.                                                                                                                     |
| `-32013` | Transaction signature length mismatch.                                                                                                                                                                                              | The number of signatures does not match the message. Rebuild the transaction.                                                                                    |
| `-32014` | Block status is not available yet for this slot.                                                                                                                                                                                    | Retry shortly.                                                                                                                                                   |
| `-32015` | Unsupported transaction version.                                                                                                                                                                                                    | Pass `"maxSupportedTransactionVersion": 1`. See [Transaction version errors](#transaction-version-errors).                                                       |
| `-32016` | Minimum context slot not reached. The node has not yet seen the `minContextSlot` you asked for.                                                                                                                                     | Retry shortly.                                                                                                                                                   |
| `-32017` | Epoch rewards are still being paid out.                                                                                                                                                                                             | Retry after the rewards period ends.                                                                                                                             |
| `-32018` | The slot is not an epoch boundary, so rewards cannot be found.                                                                                                                                                                      | Check the epoch or slot you passed.                                                                                                                              |
| `-32019` | For `getBlock`, the block is queued for retrieval from long-term storage, or was not retrieved. See [Long-term storage responses](#long-term-storage-responses).                                                                    | Wait `Retry-After` seconds when the response carries it, then send the same request again. Otherwise retry with backoff.                                         |
| `-32020` | The transaction you filtered for was not found.                                                                                                                                                                                     | Check the signature.                                                                                                                                             |
| `-32021` | No slot history.                                                                                                                                                                                                                    | Retry later.                                                                                                                                                     |

## Transaction version errors

`getBlock`, `getTransaction` and `blockSubscribe` take a `maxSupportedTransactionVersion` parameter that says which formats your client can decode. Two errors come from getting it wrong.

|   Code   | Cause                                                                                                                                                                         | Fix                                         |
| :------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------ |
| `-32015` | The parameter is missing, or its value is below the version of a transaction in the response. The number in the message is the version the node found, not the value to send. | Send `"maxSupportedTransactionVersion": 1`. |
| `-32602` | The value is the string `"1"` instead of the integer `1`. The node rejects the whole config object, so the message does not name the field.                                   | Send the JSON number `1`, with no quotes.   |

The ceiling is raised after the client can decode the format, not before. [Transaction v1](https://docs.constant-k.com/rpc/transaction-v1/) has the full error bodies, the client minimums and the migration steps.

## Transaction errors

When preflight is on, a failed simulation returns `-32002` and the send is rejected. The `data` object holds the transaction error and the program logs:

```json
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32002,
    "message": "Transaction simulation failed: Error processing Instruction 2: custom program error: 0x1",
    "data": {
      "err": { "InstructionError": [2, { "Custom": 1 }] },
      "logs": ["Program 11111111111111111111111111111111 invoke [1]", "…"]
    }
  },
  "id": 1
}
```

| Error                            | Cause                                                                          |
| :------------------------------- | :----------------------------------------------------------------------------- |
| `BlockhashNotFound`              | The blockhash is too old or unknown to this node. A fresh one is needed.       |
| `InsufficientFundsForFee`        | The fee payer cannot pay the fee.                                              |
| `InstructionError` with `Custom` | A program returned its own error code. The program's IDL or source defines it. |
| `AlreadyProcessed`               | This exact transaction already landed. A resend is redundant.                  |

With `skipPreflight: true`, the send succeeds even if the transaction would fail. `getSignatureStatuses` gives the result: a landed but failed transaction has a non-null `err`.

In `@solana/kit`, the error carries its own context:

```ts
import {
  createSolanaRpc,
  isSolanaError,
  SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE,
  SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR,
} from "@solana/kit";

const rpc = createSolanaRpc(
  `https://rpc-newyork.constant-k.com/?api-key=${process.env.CK_API_KEY}`,
);

// wireTx: a signed, base64-encoded transaction (see Sending Transactions)
try {
  await rpc.sendTransaction(wireTx, { encoding: "base64" }).send();
} catch (e) {
  if (isSolanaError(e, SOLANA_ERROR__JSON_RPC__SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE)) {
    // Simulation failed: the logs usually say why
    console.error(e.context.logs);
    console.error(e.cause); // the transaction error
  } else if (isSolanaError(e, SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR)) {
    // Rejected by the gateway, for example 401 or 403
    console.error("HTTP", e.context.statusCode);
  } else {
    throw e;
  }
}
```

## WebSocket errors

A failed subscribe returns a JSON-RPC error frame with the codes above, for example `-32602` for a bad address, and the connection stays open.

| Code                                                | Cause                                                                                                                              | What to do                                                |
| :-------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------- |
| Close `1006`, right after the connection opens      | The key is missing or invalid, or your plan does not include WebSockets. The handshake succeeds first, so there is no close frame. | Check the key and the plan.                               |
| Close `1013`                                        | You opened connections too fast, or you are at your plan's connection limit.                                                       | Read the close reason. Back off and reconnect.            |
| `-32005` frame                                      | You are over a rate limit or at the subscription cap.                                                                              | Unsubscribe, or open another connection.                  |
| `-32602` frame on `blockSubscribe`                  | The options object is missing `"maxSupportedTransactionVersion": 1`, or sent it as a string. The check runs at subscribe time.     | Send the integer `1`.                                     |
| `-32600` frame with `"id": null`, every few seconds | Your client is sending its own `ping` message. The stream is healthy.                                                              | Ignore it. See [WebSockets](https://docs.constant-k.com/rpc/websockets/#keepalives). |
| Error frame for a non-subscription method           | Only subscription methods and `getHealth` are allowed.                                                                             | Send the call over HTTPS.                                 |

## gRPC errors

These apply to [Kaldera](https://docs.constant-k.com/kaldera/), [Turbo Kaldera](https://docs.constant-k.com/kaldera/turbo-kaldera/) and [ShredPrism](https://docs.constant-k.com/shredprism/).

| Status                 | When                                                                                   | What to do                                                                            |
| :--------------------- | :------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------ |
| `UNAUTHENTICATED` (16) | The `x-token` header is missing or wrong. The message is `Missing or Invalid API Key`. | Check the key and the header name.                                                    |
| `INVALID_ARGUMENT` (3) | The subscribe request is malformed or breaks a filter limit.                           | Check the request against [Filters](https://docs.constant-k.com/kaldera/filters/) and the plan limits.           |
| `OUT_OF_RANGE` (11)    | In standard Yellowstone, `fromSlot` is older than the replay window.                   | Resubscribe with a newer slot, or without `fromSlot`. See [Replay](https://docs.constant-k.com/kaldera/replay/). |
| `UNAVAILABLE` (14)     | The connection dropped or the server is restarting.                                    | Reconnect with exponential backoff.                                                   |

Some clients report a failed login differently:

* `@triton-one/yellowstone-grpc` (TypeScript): `failed to open subscribe stream`.
* `grpcurl` and other grpc-go tools: `unexpected HTTP status code received from server: 204 (No Content)`.
* `yellowstone-grpc-client` (Rust): `code: 'The request does not have valid authentication credentials', message: "Missing or Invalid API Key"`.

## When to retry

| Retryable with exponential backoff                                                                                   | Not retryable until something changes                                                                                                    |
| :------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------- |
| Network errors, HTTP `429` and `5xx`, `-32603`, `-32005`, `-32004`, `-32014`, `-32016`, `-32019`, gRPC `UNAVAILABLE` | `400`, `401`, `403`, `-32600`, `-32601`, `-32602`, `-32002`, `-32003`, `-32013`, `-32015`, gRPC `UNAUTHENTICATED` and `INVALID_ARGUMENT` |

Backoff starts at about 250 ms, doubles each time, carries random jitter, and caps at a few seconds. A response with a `Retry-After` header sets the wait instead. WebSocket and gRPC streams use the same backoff, then resubscribe.
