# How ego-lite Handles SESSION_LOST Errors During CDP Communication

> Learn how ego-lite automatically handles SESSION_LOST errors in CDP communication by invalidating stale sessions, attaching new ones, and retrying commands.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: internals
- Published: 2026-08-26

---

**ego-lite intercepts `SESSION_LOST` errors using a regex matcher in the low-level CDP dispatcher and automatically recovers by invalidating the stale session, acquiring a new CDP session via `Target.attachToTarget`, and retrying the original command transparently.**

When browser tabs close, reload, or get reclaimed during long-running automation tasks, the underlying Chrome DevTools Protocol (CDP) session becomes invalid. The ego-lite runtime implements a resilient error-handling strategy that detects these `SESSION_LOST` conditions and manages session recovery without requiring manual intervention from calling code.

## Detecting SESSION_LOST Errors

The detection logic resides in [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts). When a CDP request is issued, the low-level `rawCdp` helper forwards the command to `globalThis.ego.sendCDPMessage`. If the browser reports a missing session, the error message is tested against the **SESSION_LOST** regular expression.

This regex matches fatal session states including phrases like "Session … not found", "Target closed", or "No session" (lines 9-11). By catching these patterns at the transport layer, ego-lite distinguishes between transient network failures and terminal session loss that requires re-attachment.

## Automatic Recovery Mechanism

The public `browserCdp` function wraps `rawCdp` in a `try / catch` block to implement transparent recovery. When a caught error satisfies the `SESSION_LOST` test **and** the request was not explicitly targeting a specific session ID, the runtime executes a three-step recovery process:

1. **Invalidate stale state** by calling `invalidateSession()`, which clears the cached session ID and any pending dialog state (lines 46-53).
2. **Acquire a fresh session** via `ensureSession()`, which handles the negotiation of a new CDP attachment (lines 107-119).
3. **Retry the original command** using the newly created session ID, returning the result to the original caller (lines 99-102).

This flow ensures that page-level CDP commands survive tab reloads or closures without throwing errors to higher-level helpers like navigation or element resolution functions.

## Session Lifecycle and Re-Attachment

The `ensureSession()` function manages the lifecycle of the CDP session with a time-to-live (TTL) of approximately 2 seconds. When invoked, it first checks whether the cached session is still valid. If the TTL has expired or the session is missing, it performs the following actions:

- Enumerates open browser tabs using `ego.listTabs()` and selects the preferred or active tab.
- Attaches to the target using the `Target.attachToTarget` CDP method.
- Enables page-level events by issuing `Page.enable` so that downstream helpers (such as dialog trackers) receive proper events (lines 125-136).

After successful attachment, the new session ID is cached and the original CDP command is reissued with this fresh context.

## Code Example: Resilient CDP Calls

The following patterns demonstrate automatic versus explicit session handling:

```typescript
import { browserCdp } from "ego-browser";

// Page-level call: ego-lite auto-recovers if the target session vanished.
await browserCdp("Runtime.evaluate", { expression: "document.title" });

```

```typescript
import { ensureSession, browserCdp } from "ego-browser";

// Explicit session usage bypasses auto-recovery.
const session = await ensureSession();
try {
  await browserCdp("Runtime.evaluate", { expression: "1+1" }, session);
} catch (e) {
  // e may still be a SESSION_LOST error because we requested a fixed session.
  // Manual re-attachment logic would be required here.
}

```

In the first example, any `SESSION_LOST` error triggers the automatic invalidation and retry logic. In the second example, because a specific session object is provided, the runtime assumes the caller manages session lifecycle and does not intercept the error.

## Summary

- **Detection** occurs in `rawCdp` ([`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts)) using a regex that matches "Session not found" and similar CDP error strings.
- **Recovery** is handled by `browserCdp`, which catches qualifying errors and orchestrates session replacement.
- **State cleanup** via `invalidateSession()` removes stale session IDs and dialog state before re-attachment.
- **Session creation** through `ensureSession()` enforces a 2-second TTL and uses `Target.attachToTarget` to establish a new CDP connection.
- **Transparency** is maintained for page-level calls, while explicit session usage requires manual error handling.

## Frequently Asked Questions

### What triggers a SESSION_LOST error in ego-lite?

A `SESSION_LOST` error occurs when the CDP target (browser tab) closes, reloads, or detaches unexpectedly. The error surfaces through Chrome DevTools Protocol messages such as "Session not found" or "Target closed", which are matched by the regex in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) lines 9-11 according to the citrolabs/ego-lite source code.

### How does ego-lite differ between page-level and explicit session CDP calls?

Page-level calls omit a specific session ID, allowing `browserCdp` to trigger automatic recovery on session loss. Explicit session calls pass a specific session object returned by `ensureSession()`, which bypasses the retry logic and requires the caller to handle `SESSION_LOST` exceptions manually.

### What is the session TTL in ego-lite?

The cached session ID has a TTL of approximately 2 seconds. The `ensureSession()` function checks this TTL before reusing a cached session; if expired, it automatically enumerates tabs and attaches to a new target via `Target.attachToTarget`.

### Does ego-lite notify the caller when it recovers from SESSION_LOST?

No, the recovery is transparent to the caller. When `browserCdp` intercepts a session loss, it invalidates the old session, creates a new one, and returns the result of the retried command without throwing an exception or logging a warning to the calling code.