# ElementResolutionError in ego-lite: Handling Transient and Permanent Resolution Failures

> Understand ego-lite's ElementResolutionError. Learn to distinguish between transient and permanent failures for smarter retry logic in your automation scripts.

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

---

**`ElementResolutionError` is a custom error class in ego-lite that classifies resolution failures as either `transient` (retryable) or `permanent` (fatal), enabling automation scripts to implement intelligent retry logic.**

`ElementResolutionError` powers the element-resolution subsystem in **ego-lite**, an open-source browser automation framework maintained by CitroLabs. Defined in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts), this error provides granular failure classification that distinguishes between DOM elements that may appear after a short delay versus fundamentally broken or ambiguous selectors.

## What is ElementResolutionError?

`ElementResolutionError` extends the native JavaScript `Error` class to signal specific failure modes during element resolution. According to the ego-lite source code, the runtime throws this error whenever it cannot locate or interact with a target element using the supplied selector or reference.

The class exposes a `kind` property that communicates whether the failure is recoverable. This design pattern allows calling code in [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) and [`src/driver/locator.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/locator.ts) to implement polling loops that differentiate between temporary DOM states and permanent configuration errors.

## The Two Kinds of ElementResolutionError

The error type discriminates between two distinct failure modes through its string-literal `kind` property.

### Transient Errors (Retryable)

A `transient` error indicates that the element might become available if the script waits briefly. This kind covers scenarios where:

- The element is still loading or rendering
- The element exists in the DOM but is temporarily hidden
- The DOM reference has become stale and needs refresh
- Box-model data is not yet computed

The wait logic in [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) specifically checks for `err.kind === "transient"` to continue polling rather than aborting the operation.

### Permanent Errors (Non-Retryable)

A `permanent` error signals that retries would be wasteful because the selector itself is invalid or ambiguous. This kind triggers when:

- The selector syntax is malformed or evaluates to an exception
- The query matches multiple elements when exactly one is required
- Required attributes are missing or immutable

Catching a `permanent` error allows scripts to fail fast with descriptive messaging rather than consuming resources on futile polling attempts.

## Class Implementation in element-resolver.ts

The error class is implemented in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) with a straightforward constructor that accepts a message and kind discriminator:

```typescript
export class ElementResolutionError extends Error {
  kind: "transient" | "permanent";
  
  constructor(message: string, kind: "transient" | "permanent") {
    super(message);
    this.name = "ElementResolutionError";
    this.kind = kind;
  }
}

```

This structure enables TypeScript's type narrowing and allows runtime inspection via `instanceof` checks.

## Where ElementResolutionError is Raised

The ego-lite codebase raises `ElementResolutionError` in four primary contexts:

- **Selector parsing** — Thrown as `selectorResolutionError` when a selector evaluates to an exception or matches an invalid number of elements
- **Reference look-up** — Triggered when a numeric reference (`@N`) is unknown or its backend node is stale, typically returning `transient` for "Unknown ref" scenarios
- **AX role/name lookup** — Returns `transient` for zero matches (element may appear) but `permanent` for ambiguous matches exceeding one element
- **Box-model extraction** — Raises `transient` when an element lacks a usable box model, indicating the layout calculation is incomplete

## Practical Error Handling Patterns

The following patterns demonstrate how to catch and respond to `ElementResolutionError` based on its `kind`.

**Example: Conditional retry logic**

```typescript
import { ElementResolutionError } from "./element-resolver.js";

try {
  const { x, y } = await resolveElementCenter(cdp, sessionId, refMap, "#submit");
  // … use coordinates …
} catch (err) {
  if (err instanceof ElementResolutionError) {
    if (err.kind === "transient") {
      // Retry later – element may appear after a short delay
      await delay(200);
      return resolveElementCenter(cdp, sessionId, refMap, "#submit");
    }
    // Permanent – selector is wrong, abort with a helpful message
    console.error("Permanent resolution failure:", err.message);
  } else {
    throw err; // re‑throw unexpected errors
  }
}

```

**Example: Integration with wait utilities**

```typescript
import { waitFor } from "./driver/waits.js";

await waitFor(async () => {
  try {
    await resolveElementCenter(cdp, sessionId, refMap, "role:button[name=Submit]");
    return true; // success
  } catch (e) {
    if (e instanceof ElementResolutionError && e.kind === "transient") {
      return false; // keep waiting
    }
    throw e; // permanent → stop waiting immediately
  }
});

```

## Summary

- **`ElementResolutionError`** is defined in [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) and extends the native `Error` class
- The error provides a **`kind`** property with two values: `"transient"` for retryable failures and `"permanent"` for fatal selector errors
- **Transient** errors indicate the element may appear after a delay (loading, hidden, stale), while **permanent** errors indicate malformed selectors or ambiguous matches
- The class is used throughout [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) and [`src/driver/locator.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/locator.ts) to drive intelligent polling and failure logic
- Callers should use `instanceof ElementResolutionError` and inspect `err.kind` to decide between retrying and aborting

## Frequently Asked Questions

### How do I properly catch ElementResolutionError in ego-lite?

Import the class from [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) and use an `instanceof` check within your catch block. This ensures you only handle the specific resolution error while allowing other unexpected errors to propagate naturally.

### What causes a transient ElementResolutionError?

Transient errors occur when the target element exists in the page logic but is not currently resolvable due to timing. Common causes include network delays preventing DOM updates, CSS animations hiding the element, or stale references requiring a refresh cycle.

### Why would a selector trigger a permanent ElementResolutionError?

Permanent errors indicate that the selector itself is the problem. This includes syntax errors in the selector string, queries that resolve to multiple elements when only one is expected, or attempts to reference attributes that do not exist on the matched element.

### Which ego-lite files should I examine to understand resolution error handling?

Study [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) for the class definition, [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) for retry-loop implementations, [`src/driver/locator.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/locator.ts) for locator-specific handling, and `src/element-resolver.test.mjs` for unit tests demonstrating expected behavior patterns.