{"record":{"id":"5105f8d807e70139","repo":"grafana/k6","slug":"getting-iframe-frame-w","errorCode":null,"errorMessage":"getting iframe frame: %w","messagePattern":"getting iframe frame: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":654,"sourceCode":"\tbeforeFrame, afterFrame := h.splitSelectorAtFrame(parsedSelector, frameNavIndex)\n\n\t// Find the iframe element using the \"before frame\" selector\n\tiframeSelector := h.reconstructSelector(beforeFrame)\n\n\tiframeHandle, err := h.waitForSelector(apiCtx, iframeSelector, opts)\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"finding iframe with selector %q: %w\", iframeSelector, err)\n\t}\n\n\t// This is a valid response from waitForSelector. It means that the element\n\t// was either hidden or detached.\n\tif iframeHandle == nil {\n\t\treturn nil, \"\", ErrElementNotVisible\n\t}\n\n\tframe, err := iframeHandle.ContentFrame()\n\tif err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"getting iframe frame: %w\", err)\n\t}\n\n\t// Wait for selector in the iframe using the \"after frame\" selector\n\tafterFrameSelector := h.reconstructSelector(afterFrame)\n\n\treturn frame, afterFrameSelector, nil\n}\n\nfunc (h *ElementHandle) waitForSelector(\n\tapiCtx context.Context, selector string, opts *FrameWaitForSelectorOptions,\n) (*ElementHandle, error) {\n\tparsedSelector, err := NewSelector(selector)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Check for frame navigation in the selector\n\tframeNavIndex := h.findFrameNavigationIndex(parsedSelector)","sourceCodeStart":636,"sourceCodeEnd":672,"githubUrl":"https://github.com/grafana/k6/blob/3fcf5388d78cb382f0c0d42ec556a06bfd1b8dee/internal/js/modules/k6/browser/common/element_handle.go#L636-L672","documentation":"After stepIntoFrame() successfully found the iframe element, calling ContentFrame() on its handle failed. ContentFrame performs a CDP dom.DescribeNode and maps the node's FrameID to a known frame; the wrapped error is either the DescribeNode CDP failure, 'element is not an iframe', or 'frame not found for id ...' (the frame is not yet registered with the frame manager).","triggerScenarios":"Chained frame-crossing selectors where the found element is not actually an iframe, the iframe's content frame hasn't been attached/registered yet (still loading or about:blank swap), or the CDP session target is gone; races where the iframe navigates between being found and described.","commonSituations":"Selectors matching a div that looks like an iframe wrapper; same-origin iframes still initializing; dynamic iframe src swaps (OAuth popup-style flows embedded inline); pages destroying/recreating iframes during load.","solutions":["Confirm the selector matches a real <iframe> element: tagName check via evaluate","Wait for the frame to be registered: page.waitForFrame({ url/name }) or wait for a known element inside the frame before chaining","Retry once after a short delay — registration races clear once loading completes","Use the frame API directly (page.frame({ name }) / frameLocator) instead of chained '>>' selectors for dynamically-swapped iframes"],"exampleFix":"// before\nawait page.locator('iframe#widget >> button').click();\n\n// after\nawait page.waitForFrame({ name: 'widget' });\nconst frame = page.frame({ name: 'widget' });\nawait frame.locator('button').click();","handlingStrategy":"validation","validationCode":"const el = await page.$('iframe#widget');\nconst tag = await el.evaluate((n) => n.tagName);\nif (tag !== 'IFRAME') throw new Error(`selector matched <${tag}>, not an iframe`);","typeGuard":"async function isIframeHandle(el) {\n  return (await el.evaluate((n) => n.tagName)) === 'IFRAME';\n}","tryCatchPattern":"try {\n  const frame = await el.contentFrame();\n} catch (e) {\n  if (/getting iframe frame/.test(String(e))) {\n    await page.waitForFrame({ url: /widget/ });\n    const frame = await (await page.$('iframe#widget')).contentFrame();\n  } else throw e;\n}","preventionTips":["Verify the element is a real <iframe> before stepping into it","Use page.waitForFrame to let the frame register before contentFrame()","Prefer the frame API over chained selectors when iframes swap src dynamically"],"tags":["browser","iframe","content-frame","cdp","race-condition"],"backgroundTag":"iframe-frame-resolution-failed","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"}