# What Triggers Session Re-Attachment After Session Loss in Ego-Lite?

> Discover what triggers session re-attachment in Ego-Lite after session loss. Learn how CDP errors, TTL expiration, new targets, or resets ensure seamless session continuity.

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

---

**Session re-attachment in Ego-Lite is triggered by CDP errors indicating a closed or missing session, expiration of the session TTL, navigation to a new browser target, or an explicit reset call, each of which routes through `ensureSession()` in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) to transparently establish a fresh CDP session.**

The Ego-Lite browser harness, as implemented in `citrolabs/ego-lite`, maintains a single **Chrome DevTools Protocol (CDP)** session per task-space and must recover seamlessly when that session becomes invalid. Understanding what events trigger **session re-attachment after session loss** is essential for building reliable automation scripts with this runtime. The recovery logic is centralized in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) through the **`ensureSession()`** and **`attachSession()`** helpers, which detect failure conditions and re-bind to the browser target automatically.

## CDP Errors That Trigger Session Re-Attachment

When a low-level CDP call fails with a **session-level error**, the runtime treats this as an immediate signal to re-attach. The `cdp()` wrapper inspects error responses for messages such as `Target closed`, `Session closed`, `No such session`, or `Session not found`. Upon detecting any of these, the wrapper clears the stored **`sessionId`** in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts) and forces the next operation to invoke `ensureSession()`.

Because the session identifier is removed from state, the runtime recognizes that the previous session is no longer valid. The next call to `ensureSession()` discovers the missing `sessionId` and initiates a fresh attachment sequence. This design ensures that transient browser disconnections do not propagate as unhandled exceptions to user-level code.

## Session TTL Expiration

In addition to error-driven detection, Ego-Lite enforces a **session time-to-live (TTL)** to prevent silent staleness. The default TTL is two seconds, tracked via the `sessionAt` timestamp in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts).

Each time `ensureSession()` runs, it compares `state.sessionAt` against `Date.now()`. If the elapsed time exceeds the TTL threshold, the existing session is considered stale even if no explicit CDP error occurred. The runtime then discards the old session metadata and calls `attachSession()` to bind a new one. This timeout check acts as a safety net for long-running tasks where the browser target may have been recycled without raising an immediate protocol error.

## Navigation and Target Changes

Page navigation can replace the underlying browser **target**, which invalidates the current CDP session. Before executing any navigation command, [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) calls `ensureSession()` to validate the connection.

If the navigation response returns a new **`targetId`** that differs from `state.sessionTargetId`, the runtime determines that the session is tied to an obsolete target. `ensureSession()` flags the mismatch and triggers `attachSession()` to re-bind to the new target. The updated `sessionId` and `sessionTargetId` are then persisted back to [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts), allowing subsequent commands to operate against the correct page context.

## Explicit Reset Requests

User code can also force re-attachment by calling an explicit reset helper such as `await ego.resetSession()` or a similar internal method. This clears the stored `sessionId`, `sessionAt`, and `sessionTargetId` values in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts).

After the state is wiped, the helper calls `ensureSession()`, which sees the empty session fields and proceeds through the standard `attachSession()` flow. This pattern is useful when automation logic requires a guaranteed clean CDP context before critical operations.

## How the Re-Attachment Flow Works

According to [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) (lines 92–107), the re-attachment sequence follows four concrete steps whenever session loss is detected:

1. `ensureSession()` evaluates the current session for three failure conditions: a missing or cleared `sessionId`, TTL expiration, or a `targetId` mismatch.

2. If any check fails, it delegates to `attachSession()` to build a new connection.

3. `attachSession()` sends the **`Target.attachToTarget`** CDP command, enables required domains such as `Page` and `Network`, and writes the new identifiers into [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts).

4. The original caller receives the fresh `sessionId` and continues transparently, with no manual retry logic required at the application layer.

This centralized recovery mechanism means that CDP session failures are handled automatically inside the runtime rather than surfacing to the end user.

## Code Examples

The following patterns demonstrate how Ego-Lite handles session recovery transparently. In each case, `ensureSession()` runs internally and re-attaches automatically if the previous session was lost.

### Automatic Recovery During a Click

```typescript
import { click } from 'ego-browser';

await click('button#submit');

```

Internally, the click helper calls `ensureSession()`. If the prior session was closed, the runtime re-attaches before executing the DOM action.

### Manual Session Validation

```typescript
import { ensureSession } from 'ego-browser';

const sessionId = await ensureSession();
console.log('Using session:', sessionId);

```

Calling `ensureSession()` directly guarantees that the returned `sessionId` is valid and fresh, performing a re-attachment only when necessary.

### Low-Level CDP with Implicit Recovery

```typescript
import { cdp } from 'ego-browser';

const result = await cdp('DOM.getDocument');

```

The `cdp()` wrapper invokes `ensureSession()` before transmitting the protocol message. If the stored session was lost, a new one is created silently and the command proceeds.

## Summary

- **CDP error messages** such as `Target closed`, `Session closed`, or `No such session` trigger immediate session re-attachment by clearing the stored `sessionId` in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts).
- **Session TTL expiration** (default two seconds) causes `ensureSession()` to treat the session as stale and invoke `attachSession()` automatically.
- **Navigation events** in [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) that yield a new `targetId` force a refresh of the CDP session to match the current browser target.
- **Explicit reset requests** wipe session state and route through `ensureSession()` to acquire a clean CDP context.
- The entire recovery flow is centralized in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) and operates transparently without requiring manual intervention in user scripts.

## Frequently Asked Questions

### What CDP errors cause Ego-Lite to detect session loss?

Errors containing `Target closed`, `Session closed`, `No such session`, or `Session not found` are caught by the `cdp()` wrapper and interpreted as fatal session loss. The wrapper clears the active `sessionId` in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts) and defers to `ensureSession()` for recovery.

### How long does an Ego-Lite CDP session remain valid?

The default session TTL is two seconds. If `ensureSession()` is invoked after this window has elapsed, the runtime discards the old session and re-attaches to the target, even if no explicit CDP error occurred.

### Does navigation always trigger a session re-attachment?

Not every navigation triggers re-attachment. Re-attachment occurs only when [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) detects that the navigation resulted in a new `targetId` that differs from `state.sessionTargetId`. If the target remains the same, the existing session continues to be used.

### Can I force a session re-attachment manually in Ego-Lite?

Yes. Calling a reset helper such as `await ego.resetSession()` clears `sessionId`, `sessionAt`, and `sessionTargetId` from state and then calls `ensureSession()`. This forces the runtime to execute the full `attachSession()` flow and return a fresh CDP session.