# Reliability (/solana-rpc/reliability)

> Which Corvus Solana RPC errors are retryable, how gRPC and aRPC streams recover, and why acceptance of a transaction is not confirmation.



Every gateway failure carries a code and a stable message prefix, and between them they tell you whether a second attempt could ever work, and what to change before you make it.

## Retrying

| Code and prefix                                                | HTTP | Retryable | What to change before the next attempt                                                                                |
| -------------------------------------------------------------- | ---: | --------- | --------------------------------------------------------------------------------------------------------------------- |
| `-32600` `Invalid request body`                                |  400 | No        | Fix serialization. The identical body will fail forever.                                                              |
| `-32002` `Unauthorized`                                        |  401 | No        | Wrong egress IP, missing token, or wrong tokenized path.                                                              |
| `-32003` `You have no access to this service`                  |  403 | No        | The resource does not include that product. Ask on [Discord](https://discord.gg/corvus-labs).                         |
| `-32001` `RPS limit exceeded`                                  |  429 | Yes       | Reduce **weighted** cost, not request count; batch items and `getMultipleAccounts` accounts are charged individually. |
| `-32005` `Transaction rate limit exceeded`                     |  429 | Yes       | Pace to your TPS allowance, then resend the same signed bytes while the blockhash is valid.                           |
| `-32005` `Scan request timed out waiting for concurrency slot` |  429 | Yes       | Lower scan concurrency first. Retrying at the same concurrency re-enters the same queue.                              |
| `-32000` `Unable to process Batch Request`                     |  502 | Yes       | Split the batch and retry idempotent items individually.                                                              |
| `-32099` `Server is not available at the moment`               |  503 | Yes       | Retry idempotent reads with bounded backoff.                                                                          |

Classify on status **and** code **and** prefix, never on the message alone; messages can pick up a trailing support sentence, and `-32005` covers two conditions.

```ts
// Terminal at the gateway: a second identical request cannot succeed.
const terminal = new Set([-32600, -32002, -32003]);

function shouldRetry(httpStatus: number, code: number) {
  if (terminal.has(code)) return false;
  return httpStatus === 429 || httpStatus === 502 || httpStatus === 503;
}
```

We reject rather than queue, so any pacing happens on your side.

## Recover gRPC and aRPC streams

### Liveness

aRPC v2 sends a **server heartbeat every 10 seconds**. That's your liveness signal.

<Callout type="warn" title="Sequence gaps cannot happen">
  aRPC v2 `sequence` starts at 0 inside each per-stream handler and increments right before every message goes out. It's a contiguous per-stream counter over everything on that stream, so you can never observe a gap. A "sequence discontinuity" detector reports nothing, and hides real loss behind a green metric while it does. Keep `sequence` for ordering and logging.
</Callout>

`sequence` is connection-local, resets on reconnect, and isn't a replay cursor. Neither the legacy nor the v2 aRPC API has a resume request, so after a reconnect you send the whole subscription set again and reconcile what you missed through JSON-RPC.

Yellowstone gRPC is the exception: pass `from_slot` on the re-subscribe and the stream replays what the backend retains from that slot before going live. [Replay on reconnect](/solana-rpc/grpc/usage#reconnect-after-a-failure) has the contract.

### Filter updates

Registrations are acknowledged per filter with a `FilterValidationResult`; unregistrations aren't acknowledged, and an entry with an empty `filter_id` is skipped. Batch related filters into one registration message and match results by `filter_id`; [aRPC limits & operations](/arpc/limits) has the rest of the aRPC stream contract.

### Two rejections behave unlike the rest

Opening and cancelling streams too rapidly is handled one layer down and never reaches you as a gRPC reason: the server closes the connection with an HTTP/2 `GOAWAY` carrying `ENHANCE_YOUR_CALM`. What you back off there is the *churn*, not just the connection.

A `PERMISSION_DENIED` carrying `PPS limit requirement not met` closes the connection, and the next connection meets exactly the same condition; see [Gateway & streaming errors](/solana-rpc/errors#pps-limit-requirement-not-met).

## Confirm transactions by signature

<Callout type="error" title="Acceptance is not confirmation">
  A `200` response, a returned signature, a QUIC acknowledgement, a sent UDP datagram: they all mean the bytes were accepted for submission, not that the transaction landed. Confirm the signature through Solana RPC.
</Callout>

Falcon does have signature-keyed duplicate suppression, but it only applies **after a submission has been delivered**. So resending the same signed bytes while the blockhash is valid is still the right retry: it isn't wasted, and it isn't blocked.

Three Falcon rejections are properties of the transaction itself (size, tip amount, tip recipient) and need a rebuild and a re-sign rather than a retry. [Falcon errors & retries](/falcon/errors) and [Tips](/falcon/tips) have the exact rules.

## Treat streaming data as pre-execution

aRPC and Shredstream hand you data before it executes. That's the point of them, and it's also the risk:

* Slot `COMPLETE` is **not** confirmation and **not** finality.
* Shredstream is fire-and-forget UDP: loss, reordering and duplication are all normal.

## Network path

Regional failure is handled behind the endpoint: backends are health-checked, and a degraded region serves you from a healthy one until it recovers ([regional failover](/platform/regions#regional-failover)). Solana RPC is served from five metros while Falcon, aRPC and Shredstream run in nine, so if you rent a second region for your own redundancy, it may not carry every product you use. See [Regions](/platform/regions).
