{"record":{"id":"987534ecb30297cd","repo":"grafana/k6","slug":"finding-clickable-point-w","errorCode":null,"errorMessage":"finding clickable point: %w","messagePattern":"finding clickable point: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":219,"sourceCode":"\tcase bool:\n\t\treturn &v, nil\n\t}\n\n\treturn nil, fmt.Errorf(\n\t\t\"checking state %q of element %q\", state, reflect.TypeOf(result))\n}\n\nfunc (h *ElementHandle) click(p *Position, opts *MouseClickOptions) error {\n\treturn h.frame.page.Mouse.click(p.X, p.Y, opts)\n}\n\n// This will get the clickable point of the element relative to the page even\n// when the element is in an iframe. In some cases this isn't the case and we\n// need to translate the point to the page.\nfunc (h *ElementHandle) clickablePoint() (*Position, error) {\n\tr, err := h.BoundingBox()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"finding clickable point: %w\", err)\n\t}\n\treturn &Position{X: r.X + r.Width/2, Y: r.Y + r.Height/2}, nil\n}\n\nfunc (h *ElementHandle) dblclick(p *Position, opts *MouseClickOptions) error {\n\treturn h.frame.page.Mouse.click(p.X, p.Y, opts)\n}\n\n// DefaultTimeout returns the default timeout for this element handle.\n// If the receiver or any of the chained fields are nil (which can happen\n// when the element handle is no longer attached to a live frame), the\n// package-level DefaultTimeout constant is returned instead of panicking.\nfunc (h *ElementHandle) DefaultTimeout() time.Duration {\n\tif h == nil || h.frame == nil || h.frame.manager == nil || h.frame.manager.timeoutSettings == nil {\n\t\treturn DefaultTimeout\n\t}\n\treturn h.frame.manager.timeoutSettings.timeout()\n}","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/element_handle.go#L201-L237","documentation":"ElementHandle.clickablePoint() computes the center of an element for pointer actions (click, dblclick, hover) by calling BoundingBox(). This error wraps a BoundingBox failure: most often 'element is not visible: ... Could not compute box model', because chromium cannot produce a box model for an element that is hidden, has no layout object, or is detached from the DOM.","triggerScenarios":"Calling click()/dblclick()/hover() on an element with display:none or visibility:hidden, an element with zero width/height, a handle whose node was removed from the DOM after it was queried, or a handle whose CDP objectID went stale after page navigation.","commonSituations":"Handle grabbed before SPA hydration finishes; CSS animations leaving the element at 0x0; element inside a collapsed or hidden iframe; reusing an ElementHandle stored across page.reload() or navigation.","solutions":["Re-locate the element immediately before the action instead of reusing an old handle","Wait for visibility first: await page.waitForSelector(sel, { state: 'visible' }) or use a locator with auto-waiting","Raise the action timeout option and/or browser.set_default_timeout for slow pages","If the element is intentionally hidden and must still be clicked, pass { force: true } to skip actionability checks","Inspect the wrapped error text: if it mentions 'target closed' or CDP failures, the page/session died rather than the element being invisible"],"exampleFix":"// before\nconst btn = await page.$('#submit');\nawait sleep(5000); // page re-renders, node replaced\nawait btn.click(); // finding clickable point: element is not visible\n\n// after\nawait page.waitForSelector('#submit', { state: 'visible' });\nconst btn = await page.$('#submit');\nawait btn.click();","handlingStrategy":"validation","validationCode":"// Verify geometry exists before any pointer action\nconst box = await handle.boundingBox();\nif (!box || box.width === 0 || box.height === 0) {\n  await page.waitForSelector(sel, { state: 'visible' });\n}\nawait handle.click();","typeGuard":null,"tryCatchPattern":"try {\n  await handle.click();\n} catch (e) {\n  if (String(e).includes('element is not visible')) {\n    // re-locate and retry once with a fresh handle\n    await (await page.waitForSelector(sel, { state: 'visible' })).click();\n  } else { throw e; }\n}","preventionTips":["Always re-locate elements right before interacting; never cache handles across renders","Wait for state 'visible' before pointer actions","Treat zero-width/height elements as not-yet-clickable"],"tags":["browser","element-handle","actionability","visibility","cdp"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}