{"record":{"id":"115b89396bb5b6a5","repo":"can1357/oh-my-pi","slug":"drag-role-element-has-no-bounding-box-likely-n","errorCode":null,"errorMessage":"Drag ${role} element has no bounding box (likely not visible): ${target}","messagePattern":"Drag (.+?) element has no bounding box \\(likely not visible\\): (.+?)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/tab-worker.ts","lineNumber":1988,"sourceCode":"\t\tconst resolveDragPoint = async (\n\t\t\ttarget: DragTarget,\n\t\t\trole: \"from\" | \"to\",\n\t\t): Promise<{ x: number; y: number; handle?: ElementHandle }> => {\n\t\t\tif (typeof target === \"string\") {\n\t\t\t\tconst handle =\n\t\t\t\t\tparseAriaRefSelector(target) !== null\n\t\t\t\t\t\t? await this.#resolveAriaRef(target)\n\t\t\t\t\t\t: asElementHandle(await untilAborted(signal, () => page.$(normalizeSelector(target))));\n\t\t\t\tif (!handle) throw new ToolError(`Drag ${role} selector did not resolve: ${target}`);\n\t\t\t\tconst box = (await untilAborted(signal, () => handle.boundingBox())) as {\n\t\t\t\t\tx: number;\n\t\t\t\t\ty: number;\n\t\t\t\t\twidth: number;\n\t\t\t\t\theight: number;\n\t\t\t\t} | null;\n\t\t\t\tif (!box) {\n\t\t\t\t\tawait handle.dispose().catch(() => undefined);\n\t\t\t\t\tthrow new ToolError(`Drag ${role} element has no bounding box (likely not visible): ${target}`);\n\t\t\t\t}\n\t\t\t\treturn { x: box.x + box.width / 2, y: box.y + box.height / 2, handle };\n\t\t\t}\n\t\t\tif (\n\t\t\t\ttarget !== null &&\n\t\t\t\ttypeof target === \"object\" &&\n\t\t\t\ttypeof (target as { x: unknown }).x === \"number\" &&\n\t\t\t\ttypeof (target as { y: unknown }).y === \"number\"\n\t\t\t) {\n\t\t\t\treturn { x: (target as { x: number }).x, y: (target as { y: number }).y };\n\t\t\t}\n\t\t\tthrow new ToolError(\n\t\t\t\t`Drag ${role} must be a selector string or { x: number, y: number } point. Got: ${typeof target}`,\n\t\t\t);\n\t\t};\n\t\tconst start = await resolveDragPoint(from, \"from\");\n\t\tlet end: { x: number; y: number; handle?: ElementHandle } | undefined;\n\t\ttry {","sourceCodeStart":1970,"sourceCodeEnd":2006,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/tab-worker.ts#L1970-L2006","documentation":"After resolving a drag endpoint selector to an element, the worker calls boundingBox(). A null box means the element is not rendered in layout (display:none, detached, or zero-size), so no drag point can be computed. The handle is disposed and this ToolError names the failing endpoint and target.","triggerScenarios":"tab.drag() with a selector endpoint whose element has no layout box: hidden via display:none/visibility:hidden, detached from the document, inside a collapsed container, or the element exists only in another frame so its box cannot be computed.","commonSituations":"Dragging from a hidden template node; target inside a closed accordion/modal; element scrolled far offscreen in a virtualized list and recycled; CSS media/state (e.g. hover-only menus) hiding the element at call time.","solutions":["Make the element visible before dragging (open its container/accordion, remove display:none).","Verify the element is attached and has size via getBoundingClientRect() before calling drag.","Use { x, y } coordinates of a visible proxy element instead of the hidden one.","For offscreen elements, scroll the container first, re-observe, then drag with the fresh ref."],"exampleFix":"// before\nawait tab.drag({ from: \"#hidden-handle\", to: \"#drop\" }); // #hidden-handle is display:none\n// after\nawait tab.evaluate(() => { document.querySelector(\"#panel\").classList.add(\"open\"); });\nawait tab.drag({ from: \"#hidden-handle\", to: \"#drop\" });","handlingStrategy":"validation","validationCode":"const visible = await tab.evaluate((sel) => {\n  const el = document.querySelector(sel);\n  return !!el && !!el.getBoundingClientRect().width && !!el.getBoundingClientRect().height;\n}, selector);\nif (!visible) throw new Error(`drag endpoint not visible: ${selector}`);","typeGuard":null,"tryCatchPattern":"try {\n  await tab.drag({ from, to });\n} catch (err) {\n  if (err.message.includes(\"no bounding box\")) {\n    await tab.evaluate((sel) => (document.querySelector(sel))?.scrollIntoView(), targetSelector);\n    return tab.drag({ from, to });\n  }\n  throw err;\n}","preventionTips":["Scroll elements into view before dragging","Open containers/accordions that hide the endpoint","Check getBoundingClientRect() width/height before the call","Use visible proxy elements or coordinates when the true target is hidden"],"tags":["browser","drag","visibility","bounding-box"],"backgroundTag":"element-not-visible","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}