{"record":{"id":"5b5cd6c4a466029e","repo":"grafana/k6","slug":"frame-not-found-for-id-s","errorCode":null,"errorMessage":"frame not found for id %s","messagePattern":"frame not found for id (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":867,"sourceCode":"}\n\n// ContentFrame returns the frame that contains this element.\nfunc (h *ElementHandle) ContentFrame() (*Frame, error) {\n\tvar (\n\t\tnode *cdp.Node\n\t\terr  error\n\t)\n\taction := dom.DescribeNode().WithObjectID(h.remoteObject.ObjectID)\n\tif node, err = action.Do(cdp.WithExecutor(h.ctx, h.session)); err != nil {\n\t\treturn nil, fmt.Errorf(\"getting remote node %q: %w\", h.remoteObject.ObjectID, err)\n\t}\n\tif node == nil || node.FrameID == \"\" {\n\t\treturn nil, fmt.Errorf(\"element is not an iframe\")\n\t}\n\n\tframe, ok := h.frame.manager.getFrameByID(node.FrameID)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"frame not found for id %s\", node.FrameID)\n\t}\n\n\treturn frame, nil\n}\n\n// Dblclick scrolls element into view and double clicks on the element.\nfunc (h *ElementHandle) Dblclick(opts *ElementHandleDblclickOptions) error {\n\tdblclick := func(_ context.Context, handle *ElementHandle, p *Position) (any, error) {\n\t\treturn nil, handle.dblclick(p, opts.ToMouseClickOptions())\n\t}\n\tdblclickAction := h.newPointerAction(dblclick, &opts.ElementHandleBasePointerOptions)\n\tif _, err := call(h.ctx, dblclickAction, opts.Timeout); err != nil {\n\t\treturn fmt.Errorf(\"double clicking on element: %w\", err)\n\t}\n\n\tapplySlowMo(h.ctx)\n\n\treturn nil","sourceCodeStart":849,"sourceCodeEnd":885,"githubUrl":"https://github.com/grafana/k6/blob/3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee/internal/js/modules/k6/browser/common/element_handle.go#L849-L885","documentation":"Thrown by ElementHandle.ContentFrame()/OwnerFrame() in k6's browser module. The handle's node is described via CDP DOM.describeNode to get its FrameID, but the frame manager has no live frame registered under that ID. This means the frame owning the element was detached, destroyed, or never attached to the frame tree.","triggerScenarios":"Calling contentFrame() on an iframe element handle after the frame navigated away, was removed from the DOM, or its out-of-process target was closed; calling it immediately after a page navigation before the new frame tree is attached; the SPA re-rendered and replaced the iframe node between acquiring the handle and stepping into it. Non-iframe elements fail earlier with 'element is not an iframe'.","commonSituations":"SPA frameworks (React/Vue) re-rendering and swapping iframe nodes; ad or analytics iframes removed mid-test; navigation between grabbing the handle and calling contentFrame(); cross-origin iframes whose OOPIF targets close unexpectedly.","solutions":["Re-acquire the iframe element handle (page.$ or page.locator) after the navigation/re-render and call contentFrame() again","Wait for the page/frame to settle first: page.waitForLoadState() or page.waitForNavigation() before stepping into the iframe","Verify the iframe is still connected before stepping in: const ok = await el.evaluate(e => e.isConnected && e.tagName === 'IFRAME')","Locate the frame through page.frames() by URL/name instead of stepping through the element handle"],"exampleFix":"// before\nconst el = await page.$('iframe#widget');\nconst frame = await el.contentFrame(); // frame may be gone after re-render\n\n// after\nawait page.waitForLoadState();\nconst el = await page.$('iframe#widget');\nif (!el || !(await el.evaluate(e => e.isConnected))) {\n  throw new Error('iframe removed from DOM; re-query the handle');\n}\nconst frame = await el.contentFrame();","handlingStrategy":"validation","validationCode":"// Before stepping into an iframe, confirm it is still an attached IFRAME node\nconst el = await page.$('iframe#widget');\nconst ok = el && await el.evaluate((e) => e.isConnected && e.tagName === 'IFRAME');\nif (!ok) {\n  throw new Error('iframe no longer attached; re-query before contentFrame()');\n}\nconst frame = await el.contentFrame();","typeGuard":null,"tryCatchPattern":"try {\n  const frame = await el.contentFrame();\n} catch (e) {\n  if (/frame not found/.test(String(e.message))) {\n    // frame was detached: re-query the element and retry once\n    const fresh = await page.$('iframe#widget');\n    frame = fresh ? await fresh.contentFrame() : null;\n  } else throw e;\n}","preventionTips":["Never cache iframe element handles across navigations or re-renders","Wait for page.waitForLoadState() before stepping into frames","Prefer page.frames() lookup by URL/name over traversing element handles when the frame is long-lived"],"tags":["browser","iframe","frame","cdp","stale-element","k6"],"backgroundTag":"frame-not-found","analyzedSha":"3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}