# Troubleshooting (/solana-rpc/troubleshooting)

> Diagnose Corvus Solana RPC failures from the exact error string: weighted 429s, PPS stream closes, and aRPC filter validation.



Find the string your client actually printed and start from there. On Corvus it's the message prefix rather than the HTTP status that tells you what went wrong, so the entries below are keyed to what you'd see.

## Connection and transport

<Accordions>
  <Accordion title="TLS handshake fails, or the client hangs on connect with https:// or wss://">
    Corvus endpoints don't do TLS. Use the `http://` or `ws://` form of the endpoint, and insecure channel credentials on `:10101` and `:20202`. See [transport security](/platform/access#transport-security).
  </Accordion>

  <Accordion title="Works from one host, fails from another">
    Standard regional endpoints authenticate you by registered public egress IP.

    Find the address the failing host actually egresses from, observed on that host over that network path, and compare it with the allowlist in your [dashboard](https://dashboard.corvus-labs.io). If restarts or autoscaling keep moving it, pin egress to a static address.
  </Accordion>

  <Accordion title="The region I want has no RPC endpoint">
    The products don't cover the same metros. Solana RPC (JSON-RPC, WebSocket and Yellowstone gRPC) runs in **five**: Frankfurt, Amsterdam, London, New York and Tokyo. Falcon, aRPC and Shredstream run in **nine**. [Regions](/platform/regions) has the grid.
  </Accordion>
</Accordions>

## Authentication and access

<Accordions>
  <Accordion title="401 with -32002 Unauthorized">
    Something in the request didn't authenticate: an egress IP that isn't registered, missing or wrong `x-token` metadata, or a tokenized URL path that's wrong or truncated.

    Start with which access method the endpoint actually uses, because they aren't interchangeable; the tokenized URL applies only to dedicated HTTP and WebSocket endpoints, never to gRPC or aRPC.
  </Accordion>

  <Accordion title="403 with -32003 You have no access to this service">
    You authenticated fine, but the resource doesn't include the product you called: a gRPC subscription on an endpoint provisioned for JSON-RPC only, say.

    Check that your plan covers that product, and ask on [Discord](https://discord.gg/corvus-labs) to have it added.
  </Accordion>
</Accordions>

## Rate limits

<Accordions>
  <Accordion title="429 with -32001 RPS limit exceeded, but I am well under my request rate">
    RPS is charged in weighted units rather than in requests. `getProgramAccounts` costs 30 units, `getTransaction` and the token-account scans cost 10, `getAccountInfo` costs 2. `getMultipleAccounts` is charged per requested account: 2 units each below 800 plan RPS, `ceil(accounts / 20)` from 800 up and for NFT pass holders on any plan. You can't ask for more than 500 across a batch. Every item in a JSON-RPC batch is metered on its own.

    Full table: [Solana RPC rate limits](/solana-rpc/limits).
  </Accordion>

  <Accordion title="429 with -32005 Scan request timed out waiting for concurrency slot">
    Scan-class methods carry a concurrency ceiling that has nothing to do with what they cost in RPS. `getLargestAccounts` and `getSupply` cost a single unit and still take a scan slot, which is why this fires while your RPS budget looks untouched.

    Serialize the scans, or move them to a worker with its own concurrency cap.
  </Accordion>

  <Accordion title="429 with -32005 Transaction rate limit exceeded">
    This one is TPS, not RPS. `sendTransaction` costs 0 RPS units and draws on the separate transaction allowance.

    Pace your sends to the TPS you rented. Check the signature through RPC before you resend anything, and when you do resend, send the **same signed bytes** while the blockhash is still valid.
  </Accordion>

  <Accordion title="502 with -32000 Unable to process Batch Request, or 503 with -32099 Server is not available at the moment">
    Either the batch couldn't be proxied, or the service was briefly unavailable. Neither one is about your allowance, so nothing needs changing before you retry: split the batch and retry idempotent items one at a time, and for `-32099` retry idempotent reads with capped backoff.
  </Accordion>
</Accordions>

## Streams

<Accordions>
  <Accordion title="gRPC PERMISSION_DENIED with detail PPS limit requirement not met, then the connection closes">
    This is the PPS condition on the aRPC streaming transport, and it reaches you as a gRPC status, never as a JSON-RPC error. The server shuts the connection down after the rejection, and the next connection meets the same condition: the check runs at admission and wants your plan's RPS and TPS to total 500. Raise either in the [dashboard](https://dashboard.corvus-labs.io). Reference: [PPS limit requirement not met](/solana-rpc/errors#pps-limit-requirement-not-met).
  </Accordion>

  <Accordion title="I registered aRPC filters and never received a FilterValidationResult">
    An entry with an empty `filter_id` is skipped without a result, by design; nothing else about that entry is reported. Batch related filters into one registration message, match results by `filter_id`, and keep the filter set you want locally so you can resend it. See [aRPC limits & operations](/arpc/limits).
  </Accordion>

  <Accordion title="The stream is connected but no data is arriving">
    Either the transport is dead or your filter matches nothing, and the heartbeat separates the two. aRPC v2 emits a server heartbeat every **10 seconds**.

    | Observation                     | Diagnosis                                                                                      |
    | ------------------------------- | ---------------------------------------------------------------------------------------------- |
    | Heartbeats arriving, no matches | The filter is too narrow, or its registration was rejected; check its `FilterValidationResult` |
    | No heartbeat for well over 10s  | The transport is dead; reconnect and resend the full subscription set                          |

    `sequence` won't help you here: it's a contiguous per-stream counter, so gaps can't happen.
  </Accordion>

  <Accordion title="gRPC RESOURCE_EXHAUSTED on a Yellowstone subscription">
    The reason string says which ceiling you hit: `stream_limit` (too many concurrent RPCs), `filters` (too many or too broad selectors), `subscribe_rate_limit` (filter or subscription updates arriving too fast), `connection_limit` (too many concurrent connections on the transport). See [Yellowstone gRPC limits](/solana-rpc/grpc/limits).

    Streams opened and cancelled (`RST_STREAM`) too rapidly are handled a layer down and produce **no** gRPC status at all: the connection closes with an HTTP/2 `GOAWAY` / `ENHANCE_YOUR_CALM`. If your client reports a dropped connection and no status, that's this.
  </Accordion>

  <Accordion title="Shredstream: nothing arrives at my destination">
    Delivery is push-based, fire-and-forget UDP to the stable public IPv4 address and single UDP port you registered at onboarding. Nothing comes back and nothing retries, so every cause looks identical from your end.

    Confirm the address and port still match what you registered, allow inbound UDP on that port from the assigned region, and verify with a packet capture on the port rather than from the application. See [Shredstream](/platform/shredstream).
  </Accordion>
</Accordions>

## Transactions

<Accordions>
  <Accordion title="I got a signature back but the transaction never landed">
    Acceptance isn't confirmation. A `200`, a returned signature, a QUIC acknowledgement and a sent UDP datagram all mean the same thing: the bytes were accepted for submission.

    Confirm the signature through Solana RPC. While the blockhash is still valid, resending the **same signed bytes** is the right retry: Falcon's signature-keyed duplicate suppression only applies after a submission has been delivered, so you aren't blocked.
  </Accordion>

  <Accordion title="Falcon rejects the transaction before it is ever submitted">
    That's a property of the transaction rather than a transient failure, and it's usually one of three: the serialized transaction is over **1,232 bytes**, the tip is below **1,000,000 lamports** (0.001 SOL), or the tip went to an account outside the allowed Falcon tip list.

    Rebuild, re-sign, resubmit. Native UDP returns nothing at all in these cases, so validate locally before you send. See [Falcon errors & retries](/falcon/errors).
  </Accordion>
</Accordions>

## What to send support

If none of that gets you there, open a ticket on [Discord](https://discord.gg/corvus-labs). What saves a round trip:

* UTC timestamp range and region
* Product and transport (JSON-RPC, WebSocket, Yellowstone gRPC, aRPC, Falcon, Shredstream)
* HTTP status + JSON-RPC code + message prefix, or gRPC status + reason + detail prefix
* The endpoint exactly as configured, including scheme and port, secrets redacted
* The public egress IP of the failing process, observed from that host
* The method name or subscription/filter shape involved
* Client library and version
* Minimal reproduction
