{"record":{"id":"34ee0896280f7c82","repo":"grafana/k6","slug":"getting-bounding-box-model-of-dom-node-w","errorCode":null,"errorMessage":"getting bounding box model of DOM node: %w","messagePattern":"getting bounding box model of DOM node: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":68,"sourceCode":"\tframe *Frame\n}\n\n// String returns a string representation of ElementHandle.\n// It exists mostly for debugging where we don't want fmt.Sprintf to just\n// go through a complex object and try to stringify it.\nfunc (h *ElementHandle) String() string {\n\treturn \"ElementHandle{\" +\n\t\t\" BaseJSHandle:  \" + h.BaseJSHandle.String() +\n\t\t\" frame: \" + h.frame.String() +\n\t\t\"}\"\n}\n\nfunc (h *ElementHandle) boundingBox() (*Rect, error) {\n\tvar box *dom.BoxModel\n\tvar err error\n\taction := dom.GetBoxModel().WithObjectID(h.remoteObject.ObjectID)\n\tif box, err = action.Do(cdp.WithExecutor(h.ctx, h.session)); err != nil {\n\t\treturn nil, fmt.Errorf(\"getting bounding box model of DOM node: %w\", err)\n\t}\n\n\tif box == nil || box.Border == nil {\n\t\treturn nil, ErrElementNotAttachedToDOM\n\t}\n\n\tquad := box.Border\n\tx := math.Min(quad[0], math.Min(quad[2], math.Min(quad[4], quad[6])))\n\ty := math.Min(quad[1], math.Min(quad[3], math.Min(quad[5], quad[7])))\n\twidth := math.Max(quad[0], math.Max(quad[2], math.Max(quad[4], quad[6]))) - x\n\theight := math.Max(quad[1], math.Max(quad[3], math.Max(quad[5], quad[7]))) - y\n\n\tposition, err := h.frame.position()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"getting position of parent frame: %w\", err)\n\t}\n\n\treturn &Rect{X: x + position.X, Y: y + position.Y, Width: width, Height: height}, nil","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/element_handle.go#L50-L86","documentation":"ElementHandle.boundingBox issues the CDP dom.GetBoxModel call for the handle's remote object; if the protocol call fails, the error is wrapped with this text. Typical underlying failures: the node was detached/removed (stale object ID), the frame navigated away, or the session is gone.","triggerScenarios":"Calling elementHandle.boundingBox() (directly, or via click() which resolves a clickable point through it) after the element left the DOM, after a navigation replaced the document, or on a handle from a closed page.","commonSituations":"SPA re-rendering between locator query and boundingBox (React re-mounts the node); ad/promo overlays removing the target; holding element handles across page.goto and reusing them.","solutions":["Re-query the element immediately before measuring instead of reusing a stale handle.","Wait for the element to be attached/visible first (locator with waitFor / expect-style waits) before boundingBox.","Do not navigate between acquiring the handle and calling boundingBox.","If it happens inside click(), prefer locator-based clicks with a retry on this specific error."],"exampleFix":"// before\nconst el = page.locator('#submit');\nconst handle = await el.getElementHandle();\nawait page.waitForTimeout(5000);    // SPA re-renders, handle goes stale\nawait handle.boundingBox();          // getting bounding box model of DOM node: ...\n\n// after\nconst handle = await page.locator('#submit').getElementHandle(); // re-query late\nawait handle.boundingBox();","handlingStrategy":"retry","validationCode":"// re-query the element fresh instead of reusing a possibly stale handle\nconst handle = await page.locator(sel).getElementHandle();\n// measure immediately, in the same tick — no sleeps or navigations in between","typeGuard":null,"tryCatchPattern":"try {\n  await handle.boundingBox();\n} catch (e) {\n  if (/getting bounding box model of DOM node/.test(String(e))) {\n    const fresh = await page.locator(sel).getElementHandle(); // node may have been re-mounted\n    return await fresh.boundingBox();\n  }\n  throw e;\n}","preventionTips":["Never hold element handles across navigations or long waits; re-query before use.","Wait for visibility (locator.waitFor) before geometry-sensitive operations.","In dynamic SPAs, wrap boundingBox/click in a single-retry helper keyed to this message."],"tags":["element-handle","dom","bounding-box","stale-element","cdp"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}