{"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/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/element_handle.go#L636-L672","documentation":"After locating the iframe element of a frame-crossing selector, stepIntoFrame calls ContentFrame(); this wraps its failure. The cause is either a CDP DOM.describeNode error ('getting remote node'), 'element is not an iframe', or 'frame not found for id ...'.","triggerScenarios":"A frame-crossing selector whose 'before frame' part matches an element that is not actually an iframe, or an iframe that navigated/detached between being matched and ContentFrame() being called.","commonSituations":"Selector matches a div wrapper that hosts the iframe; iframe src swapped (login redirects) during the query; iframe removed by a re-render mid-wait.","solutions":["Tighten the iframe selector so it matches the <iframe> element itself","Retry after the iframe content settles (wait for a known element inside it)","Increase the timeout","Use page.frameLocator() instead of hand-built frame-crossing selectors"],"exampleFix":"// before\nawait handle.waitForSelector('#container >> button'); // matched a div, not the iframe\n\n// after\nawait handle.waitForSelector('#container iframe >> button');","handlingStrategy":"try-catch","validationCode":"const isIframe = await handle.evaluate((el) => el.tagName === 'IFRAME');\nif (!isIframe) throw new Error('selector must resolve to an iframe');","typeGuard":null,"tryCatchPattern":"try {\n  await handle.waitForSelector('iframe >> .btn');\n} catch (e) {\n  if (String(e).includes('getting iframe frame')) {\n    // matched node wasn't an iframe or it was swapped; tighten selector and retry\n    await handle.waitForSelector('#real-iframe >> .btn');\n  } else { throw e; }\n}","preventionTips":["Aim the pre-frame selector at the <iframe> element itself","Re-try after iframe src changes settle"],"tags":["browser","iframe","cdp","selector"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}