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 clickableView on GitHub (pinned to 49907e53dc)
Solutions
- Run the element-resolution step in the same frame immediately before the rect query
- Re-resolve after any navigation or reload — window.__resolved does not survive navigation
- 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
- Always resolve an element in the same frame before rect queries
- Re-resolve after navigation (window.__resolved is volatile)
- Avoid mixing resolve and query calls across frames/tabs
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
- Element not found: ref=${ref}
- Element not found: ${safeRef}
- Failed to extract Booking.com cards: ${err?.message || err}
- coupang add-to-cart evaluation failed: ${error?.message || e
- coupang search
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9c2d0b865f30479f.
Report an issue: GitHub.