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

# Handling Reconnects and Errors in Parsed Streams

> Detect Parsed Streams disconnects, reconnect with backoff, resubscribe, and backfill exactly the slot window you missed.

Delivery is **at most once** — there is no replay. Whatever confirmed while you were disconnected is not resent, so a production client needs to detect the gap and decide whether to backfill it. The signal for that is `context.slot`: it bounds the window you missed across a disconnect. This guide covers why connections close, how to reconnect cleanly, and how to use it.

## Why Connections Close

Every close has a WebSocket close code that tells you what happened and what to do next:

| Code | Reason | What to do |
| - | - | - |
| 1000 | Idle: no client messages and no notifications for 10 minutes | Reconnect and resubscribe. Protocol-level WebSocket pings that client libraries send automatically do **not** reset the idle timer. |
| 1001 | Server restart (deploy) | Reconnect and resubscribe |
| 1008 | Slow consumer: you fell more than 2048 notifications behind | Reconnect with a narrower filter, `details: "matched"` or `"raw"`, or faster processing |
| 1005 / 1006 | Network edge recycled the connection | Reconnect and resubscribe; normal at some frequency on any long-lived connection |

The server pings every 15 seconds, so a healthy but quiet connection still carries traffic. If you see nothing at all for over a minute — no notification, no ping — assume the connection is dead and reconnect rather than waiting for the socket to tell you.

## Quiet Filters and the Idle Timeout

If your filter is narrow enough that it can legitimately go 10 minutes without a match, expect the server to close the connection with code 1000. Treat it like any other close: reconnect, resubscribe, and backfill the gap as described below.

## Reconnect and Detect the Gap

**1. Reconnect with Backoff**

On any close — expected or not — reconnect with exponential backoff. Subscription ids do not survive a reconnect, so resend `parsedTransactionSubscribe` for every filter you had open.

**2. Track context.slot Across Disconnects**

Keep the last `context.slot` you saw before the disconnect. The gap between that slot and the first slot you see after reconnecting is exactly the window you missed — nothing more, nothing less.

**3. Backfill if You Need To**

If your application can't tolerate the gap, backfill that slot window from RPC: `getSignaturesForAddress` to enumerate transactions in range, then `getTransaction` to fetch each one. This is a manual reconciliation step — Parsed Streams itself does not replay.

```typescript theme={"system"}
import WebSocket from "ws";

const URL = "wss://beta.helius-rpc.com/?api-key=<API_KEY>";
const filters = [
  { programs: ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"] },
];

let lastSlotSeen: number | null = null;
let backoffMs = 1000;

function connect() {
  const ws = new WebSocket(URL);

  ws.on("open", () => {
    backoffMs = 1000;
    filters.forEach((filter, i) => {
      ws.send(JSON.stringify({
        jsonrpc: "2.0",
        id: i + 1,
        method: "parsedTransactionSubscribe",
        params: [filter],
      }));
    });
  });

  ws.on("message", (data) => {
    const msg = JSON.parse(data.toString());
    if (msg.method === "parsedTransactionNotification") {
      const { slot } = msg.params.result.context;

      // Across reconnects, the slot bounds the backfill window.
      if (lastSlotSeen !== null && slot > lastSlotSeen) {
        // backfill candidates: slots lastSlotSeen+1 .. slot-1 while disconnected
      }
      lastSlotSeen = slot;
    }
  });

  ws.on("close", (code) => {
    console.warn(`connection closed (${code}); reconnecting in ${backoffMs}ms`);
    setTimeout(connect, backoffMs);
    backoffMs = Math.min(backoffMs * 2, 30_000);
  });
}

connect();
```

`context.slot` is what survives a reconnect: track the highest slot you fully processed before the disconnect and treat everything after it as the backfill window.

## Handling JSON-RPC Errors

Requests that fail return a JSON-RPC error instead of a result, so you can branch on `error.code`:

| Code | Meaning |
| - | - |
| `-32700` | Parse error (invalid JSON) |
| `-32600` | Invalid request |
| `-32601` | Method not found |
| `-32602` | Invalid params: bad pubkey, unknown field, unsupported commitment or details value |
| `-32000` | Filter limit exceeded |
| `-32001` | Server not ready; retry with backoff |
| `-32002` | Rate limited (10 messages per second) |
| `-32006` | Too many subscriptions (25 per connection) |

`-32602` and `-32000` mean the request itself is wrong — fix the filter, don't retry it as is. `-32001` and `-32002` are transient; retry with the same backoff you use for reconnects.

## Next Steps

> [card] [Quickstart](https://www.helius.dev/docs/parsed-streams/quickstart.md)
>
> Full protocol reference: methods, filter fields, limits.

> [card] [Track Jupiter Swaps](https://www.helius.dev/docs/parsed-streams/guides/track-jupiter-swaps.md)
>
> Build a filter this connection can subscribe to.


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