jackwener/OpenCLI · error

No resolved element

Error message

No resolved element

What it means

boundingRectResolvedJs generates an in-page script that reads window.__resolved (the element resolved by a prior resolution step) to compute its bounding rect. If __resolved is unset the script throws 'No resolved element'.

Source

Thrown at src/browser/target-resolver.ts:310

      }
    })()
  `;
}

/**
 * Generate JS that scrolls + measures `__resolved` without clicking.
 *
 * Generic click prefers CDP `Input.dispatchMouseEvent`, which fires the full
 * pointer/mouse chain that Radix/MUI/shadcn dropdowns rely on. Keep measurement
 * separate so the CDP-primary path does not call DOM `el.click()` first.
 */
export function boundingRectResolvedJs(opts: { skipScroll?: boolean; forClick?: boolean } = {}): string {
  const shouldScroll = opts.skipScroll ? 'false' : 'true';
  const forClick = opts.forClick ? 'true' : 'false';
  return `
    (() => {
      const el = window.__resolved;
      if (!el) throw new Error('No resolved element');
      if (${shouldScroll}) el.scrollIntoView({ behavior: 'instant', block: 'center' });

      const FOR_CLICK = ${forClick};
      // hover()/dblClick() want the plain element centre — the retarget + hit-test
      // below are click-only so those actions keep their original behaviour.
      if (!FOR_CLICK) {
        const r0 = el.getBoundingClientRect();
        return {
          x: Math.round(r0.left + r0.width / 2),
          y: Math.round(r0.top + r0.height / 2),
          w: Math.round(r0.width),
          h: Math.round(r0.height),
          visible: Math.round(r0.width) > 0 && Math.round(r0.height) > 0,
        };
      }

      // Does this node OWN a click handler? Deliberately excludes cursor:pointer,
      // which is an *inherited* CSS property — an <svg> icon inside a clickable

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Run the element-resolution step in the same frame immediately before the rect query
  2. Re-resolve after any navigation or reload — window.__resolved does not survive navigation
  3. Ensure both resolve and rect calls target the same frame/tab

Example fix

// before
await page.rect(ref); // resolve skipped → No resolved element
// after
await page.resolve(ref);       // sets window.__resolved
await page.rect(ref);          // now reads it
Defensive patterns

Strategy: try-catch

Validate before calling

const hasResolved = await page.evaluate('!!window.__resolved');
if (!hasResolved) await page.resolve(ref); // ensure resolution ran first

Type guard

function hasResolvedElement(el: Element | undefined): el is Element { return el != null; }

Try / catch

try { const r = await page.rect(ref); }
catch (e) {
  if (e.message === 'No resolved element') {
    await page.resolve(ref);
    return await page.rect(ref);
  } throw e;
}

Prevention

When it happens

Trigger: Evaluating the boundingRectResolvedJs script (used by rect and js helpers) on a page/frame where the preceding resolve step never ran or ran in a different context, leaving window.__resolved undefined.

Common situations: After page navigation clearing the injected state; resolving in the main frame but querying in an iframe (or vice versa); skipping the resolve step before calling rect(); extension context reload wiping page state.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/9c2d0b865f30479f. Report an issue: GitHub.