> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbitflare.com/llms.txt
> Use this file to discover all available pages before exploring further.

# gRPC Debugging

> Fix Jetstream and Yellowstone gRPC connections on OrbitFlare: IP Whitelist and API Key Only access, x-token errors, TLS and port mistakes, filters that match nothing, and keepalive.

OrbitFlare runs two gRPC services. Most problems come from mixing up their hosts, ports or authentication, so check this first:

| | Jetstream | Yellowstone |
| - | - | - |
| Host | `{region}.jetstream.orbitflare.com` | `{region}.rpc.orbitflare.com` |
| Port | `80` | `10000` |
| Transport | Plaintext (`http://`) | Plaintext (`http://`) |
| Access | Whitelisted IP, or `x-token` key | Whitelisted IP, or `x-token` key |
| Filters | Transactions only | Accounts, transactions, slots, blocks, entries |

How you get in depends on your license's [authentication mode](/authentication#authentication-modes):

* **IP Whitelist:** the connection must come from an IP on your license's whitelist. No key is needed, and a key alone does not get you in from any other IP. To see the IP a server connects from, run `curl -s ifconfig.me` on it.
* **API Key Only:** send your license key in the `x-token` metadata header, from any IP. gRPC has no query string, and `x-api-key` is not accepted.

Check which mode your license is in on the [dashboard](https://orbitflare.com/dashboard) before debugging anything else.

## Check the connection with grpcurl

[grpcurl](https://github.com/fullstorydev/grpcurl) calls a gRPC method from the command line, so you can test access without writing code. Download the protos from the [SDK repository](https://github.com/orbitflare/orbitflare-sdk-ts/tree/main/protos) into the current folder, then:

```bash Jetstream theme={"theme":{"light":"github-light","dark":"github-dark-default"}}
grpcurl -plaintext -H "x-token: $ORBITFLARE_LICENSE_KEY" -import-path . -proto jetstream_v2.proto \
  -d '{}' fra.jetstream.orbitflare.com:80 jetstream.v2.JetstreamV2/GetVersion
```

```bash Yellowstone theme={"theme":{"light":"github-light","dark":"github-dark-default"}}
grpcurl -plaintext -H "x-token: $ORBITFLARE_LICENSE_KEY" -import-path . -proto geyser.proto \
  -d '{}' fra.rpc.orbitflare.com:10000 geyser.Geyser/GetVersion
```

In IP Whitelist mode you can drop the `-H` flag. A version string means the host is reachable and you are allowed in. Anything else, look it up below.

## Errors and what they mean

### Access refused

The two services report this differently, and the same message can mean different things in each [authentication mode](/authentication#authentication-modes).

| Service | What you see | IP Whitelist mode | API Key Only mode |
| - | - | - | - |
| Yellowstone | `Unauthenticated: authentication required: provide x-token header` | Your IP is not whitelisted. Whitelist it; you do not need an x-token | No `x-token` was sent. Send your license key in it |
| Yellowstone | `PermissionDenied: IP not whitelisted for this api key` | The key is valid, but the IP is not whitelisted. In this mode the key alone is not enough | The region is not on your license |
| Yellowstone | `Unauthenticated: invalid x-token: api key not found` | The x-token is not a valid key | The x-token is not a valid key. Copy it again from the dashboard |
| Jetstream | `Unavailable: error reading from server: EOF` or `connection reset by peer` | Your IP is not whitelisted | No valid `x-token` was sent |

Jetstream closes the connection before sending any gRPC status, so `EOF` or a reset is the only sign you get. If an endpoint isn't covered by your license, hitting it results in the same `EOF`, in either mode. Check which regions your license includes in the [dashboard](https://orbitflare.com/dashboard).

The SDKs wrap these with the gRPC status number and the endpoint, for example `grpc error (16): authentication required: provide x-token header` in Rust or `grpc error (14): [http://ams.jetstream.orbitflare.com] error reading from server: EOF` in Go. Status `16` is Unauthenticated, `7` is PermissionDenied and `14` is Unavailable.

If the same code works from one server and fails from another, you are almost certainly in IP Whitelist mode and the second server's IP is not on the list. If it fails everywhere in API Key Only mode, check that your client actually sends the `x-token` header.

### Wrong transport or port

| What you see | Cause | Fix |
| - | - | - |
| `tls: first record does not look like a TLS handshake` | The client used TLS against a plaintext port | Use `http://` in the URL, or `-plaintext` with grpcurl |
| `context deadline exceeded` when connecting | Wrong port, for example Jetstream on `10000` | Jetstream is on `80`, Yellowstone on `10000` |
| DNS lookup fails | The host does not exist | Check the region code in [Infrastructure](/infrastructure). Jetstream and Yellowstone have different region lists |

### Connection limit reached

`RESOURCE_EXHAUSTED: connection limit exceeded` means your IP already has 50 open gRPC connections, counted across Jetstream, Yellowstone and every region. Close streams you no longer use, and put several filters on one stream instead of opening a stream per filter. See [connection limits](/authentication#data-streaming-connection-limits).

## Connected but nothing arrives

### Jetstream

Jetstream v2 tells you whether each filter was accepted. The first message on a new stream is a `filterValidation` for every filter you sent:

```json theme={"theme":{"light":"github-light","dark":"github-dark-default"}}
{ "filterValidation": { "filterId": "pump", "accepted": true } }
{ "filterValidation": { "filterId": "bad", "rejectionReason": "invalid pubkey" } }
```

A rejected filter does not close the stream. You keep receiving heartbeats, so the connection looks healthy while nothing matches. Log `filterValidation` messages, and check `accepted` before assuming the market is quiet.

Other causes:

* **You asked for accounts.** Jetstream streams transactions only. Account filters are not supported, and a v1 subscription with an `accounts` filter never sends anything. Use [Yellowstone](/data-streaming/yellowstone-account-monitoring) to watch account state.
* **`account_required` is too strict.** `account_include` matches a transaction that mentions any of the listed accounts. `account_required` matches only transactions that mention all of them. Start with `account_include` and narrow down from there.
* **You called `SubscribeParsed`.** It is not implemented and closes with `Unavailable: EOF`. Use `Subscribe` (v1) or `SubscribeTransactions` (v2) and decode instructions yourself.

### Yellowstone

* **The filter map is empty.** A `SubscribeRequest` with no filters is valid and returns nothing. Each filter needs a name: `{"accounts": {"my-filter": {"account": ["..."]}}}`.
* **The account is not changing.** Account filters send an update only when the account changes. Test with `SysvarC1ock11111111111111111111111111111111`, which changes every slot.
* **Failed transactions are filtered out.** `failed: false` drops every transaction that errored. Leave it unset while debugging so you can see whether your transactions are landing and failing. (The `vote` filter no longer matters: since Alpenglow, validators vote off-chain and mainnet has no vote transactions.)

## Streams that stop

Idle gRPC streams are closed after about 10 minutes. Send a ping on the stream every 30 seconds:

* **Jetstream v2:** send a `ping` message on the `SubscribeTransactions` stream. The server answers with a `pong` carrying the same ID.
* **Yellowstone:** send a `SubscribeRequest` with only `ping` set. See [Yellowstone quickstart](/data-streaming/yellowstone-quickstart).

The OrbitFlare SDKs ping, detect missed pongs, reconnect with backoff and send your filters again automatically. If you use your own client, resend the full subscription after reconnecting, because filters belong to a stream and are lost with it.

## Still stuck

Collect the host and port, the method you called, the filter you sent, the exact error with its status code, and the public IP you connect from. Then ask in [Discord](https://discord.gg/orbitflare).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.