{"record":{"id":"9c2d0b865f30479f","repo":"jackwener/OpenCLI","slug":"no-resolved-element","errorCode":null,"errorMessage":"No resolved element","messagePattern":"No resolved element","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/browser/target-resolver.ts","lineNumber":310,"sourceCode":"      }\n    })()\n  `;\n}\n\n/**\n * Generate JS that scrolls + measures `__resolved` without clicking.\n *\n * Generic click prefers CDP `Input.dispatchMouseEvent`, which fires the full\n * pointer/mouse chain that Radix/MUI/shadcn dropdowns rely on. Keep measurement\n * separate so the CDP-primary path does not call DOM `el.click()` first.\n */\nexport function boundingRectResolvedJs(opts: { skipScroll?: boolean; forClick?: boolean } = {}): string {\n  const shouldScroll = opts.skipScroll ? 'false' : 'true';\n  const forClick = opts.forClick ? 'true' : 'false';\n  return `\n    (() => {\n      const el = window.__resolved;\n      if (!el) throw new Error('No resolved element');\n      if (${shouldScroll}) el.scrollIntoView({ behavior: 'instant', block: 'center' });\n\n      const FOR_CLICK = ${forClick};\n      // hover()/dblClick() want the plain element centre — the retarget + hit-test\n      // below are click-only so those actions keep their original behaviour.\n      if (!FOR_CLICK) {\n        const r0 = el.getBoundingClientRect();\n        return {\n          x: Math.round(r0.left + r0.width / 2),\n          y: Math.round(r0.top + r0.height / 2),\n          w: Math.round(r0.width),\n          h: Math.round(r0.height),\n          visible: Math.round(r0.width) > 0 && Math.round(r0.height) > 0,\n        };\n      }\n\n      // Does this node OWN a click handler? Deliberately excludes cursor:pointer,\n      // which is an *inherited* CSS property — an <svg> icon inside a clickable","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/src/browser/target-resolver.ts#L292-L328","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait page.rect(ref); // resolve skipped → No resolved element\n// after\nawait page.resolve(ref);       // sets window.__resolved\nawait page.rect(ref);          // now reads it","handlingStrategy":"try-catch","validationCode":"const hasResolved = await page.evaluate('!!window.__resolved');\nif (!hasResolved) await page.resolve(ref); // ensure resolution ran first","typeGuard":"function hasResolvedElement(el: Element | undefined): el is Element { return el != null; }","tryCatchPattern":"try { const r = await page.rect(ref); }\ncatch (e) {\n  if (e.message === 'No resolved element') {\n    await page.resolve(ref);\n    return await page.rect(ref);\n  } throw e;\n}","preventionTips":["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"],"tags":["dom","browser-automation","state","stale-reference"],"backgroundTag":"unresolved-element-state","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}