# When Does ego-browser Invalidate CDP Sessions and Clear Preferred Targets?

> Discover when ego-browser invalidates CDP sessions and clears preferred targets. Learn about lost sessions, detached targets, and method mutations. Understand ego-lite behavior for better control.

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

---

**`ego-browser` invalidates CDP sessions and clears preferred targets in three scenarios: when a CDP request reports a lost session, when a target is detached or destroyed, and after mutating task-space or ego methods.**

The `ego-browser` package in the `citrolabs/ego-lite` repository manages a single Chrome DevTools Protocol (CDP) session attached to a preferred target page. Understanding when this session state is reset helps developers debug connection issues and predict runtime behavior during automation workflows.

## CDP Session Loss Detection

The runtime automatically detects session failures through error pattern matching in `browserCdp()`. When a CDP response contains error messages matching `/Session (?:with given id )?not found|Target closed|No session/i`, the handler immediately triggers recovery.

In [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts) (lines 98-101), the error handler:

```typescript
// Simplified representation of the error detection logic
if (errorMessage.match(/Session (?:with given id )?not found|Target closed|No session/i)) {
  await invalidateSession();
  // Retry with fresh session automatically
}

```

This **automatic retry mechanism** ensures operations continue without manual intervention when a session expires or target crashes.

## Target Detachment and Destruction Events

CDP emits lifecycle events when targets change. The runtime subscribes to `Target.detachedFromTarget` and `Target.targetDestroyed` events to maintain accurate state.

From [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts) (lines 52-64):

```typescript
// Event handlers clean up when the preferred target goes away
if (detachedTargetId === state.sessionTargetId) {
  invalidateSession();
}

```

The handler performs two actions:
- Removes page-event bookkeeping and dialog trackers
- Invalidates the session only if the detached target matches the current session target

This prevents unnecessary session churn when unrelated targets close.

## Task-Space and Ego Method Mutations

State-changing operations explicitly clear both session and preferred target to guarantee clean state. The `wrapInvalidating()` decorator in [`package/ego-browser/src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts) (lines 81-89) wraps these methods:

**Wrapped methods include:**
- `useTaskSpace`
- `closeTaskSpace`
- `createTaskSpace`
- `claimTaskSpace`
- `createTab`

```typescript
// Example: claimTaskSpace automatically invalidates
await claimTaskSpace('production-env');
// Internally executes:
//   invalidateSession()
//   clearPreferredTarget()

```

This **defensive pattern** ensures that task-space isolation translates to fresh CDP connections, preventing cross-contamination between environments.

## Core Utility Functions

### invalidateSession()

Defined in [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts), this function:
- Zeros `state.sessionId` and `state.sessionTargetId`
- Clears the session timestamp
- Drops pending page-event subscriptions
- Removes dialog event trackers

### clearPreferredTarget()

Also in [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts), this simpler utility sets `state.preferredTargetId` to `null`. It is always called alongside `invalidateSession()` in the wrapper functions, though both can be invoked manually in edge cases.

```typescript
// Manual clearing (rarely needed)
await clearPreferredTarget();
await invalidateSession();

```

## Practical Recovery Patterns

The SDK handles most recovery automatically. Explicit handling is only necessary for custom CDP commands:

```typescript
// Auto-recovery example: SDK retries internally
await page.goto('https://example.com/long-running-task');

// Custom CDP with manual fallback
try {
  await browserCdp('Runtime.evaluate', { expression: 'window.__custom' });
} catch (e) {
  if (e.message.includes('Session not found')) {
    await invalidateSession();
    // Retry once before surfacing error
  }
}

```

## Summary

- **Automatic invalidation** occurs on CDP session errors matching known failure patterns in `browserCdp()`
- **Event-driven cleanup** responds to `Target.detachedFromTarget` and `Target.targetDestroyed` events
- **Mutating operations** (`useTaskSpace`, `claimTaskSpace`, `createTab`, etc.) proactively clear state via `wrapInvalidating()`
- **`invalidateSession()`** and **`clearPreferredTarget()`** are implemented in [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts) and coordinate through [`index.ts`](https://github.com/citrolabs/ego-lite/blob/main/index.ts) wrappers
- Manual intervention is rarely required; the runtime prioritizes **self-healing connections**

## Frequently Asked Questions

### What error messages trigger automatic session invalidation?

Error messages matching the regex `/Session (?:with given id )?not found|Target closed|No session/i` trigger automatic invalidation. These indicate the CDP backend has discarded the session or the target process has terminated.

### Can I prevent session invalidation during task-space switching?

No. The `wrapInvalidating()` decorator in [`index.ts`](https://github.com/citrolabs/ego-lite/blob/main/index.ts) enforces invalidation for all mutating operations to maintain isolation guarantees. This is intentional design—disabling it risks stale target references across task-space boundaries.

### How do I check the current session and preferred target state?

The runtime maintains internal `state` object with `sessionId`, `sessionTargetId`, and `preferredTargetId` fields. These are not directly exposed; instead, rely on the automatic recovery mechanisms or call `invalidateSession()` and `clearPreferredTarget()` proactively before critical operations.

### Does navigation trigger session invalidation?

Navigation helpers in [`driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/nav.ts) indirectly invoke the same invalidation wrappers, ensuring that page transitions don't leave stale session references. The invalidation occurs through the decorator pattern rather than explicit navigation hooks.