{"record":{"id":"ee6c12b4c1c1125e","repo":"grafana/k6","slug":"finding-iframe-with-selector-q-w","errorCode":null,"errorMessage":"finding iframe with selector %q: %w","messagePattern":"finding iframe with selector %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/element_handle.go","lineNumber":643,"sourceCode":"\treturn false, fmt.Errorf(\n\t\t\"waiting for states %v of element %q\", states, reflect.TypeOf(result))\n}\n\n// stepIntoFrame steps into an iframe/frame. Due to CORS, we need to perform this\n// step outside of the browser (chromium). It returns the frame that it has stepped\n// into and the selector to use within that frame.\nfunc (h *ElementHandle) stepIntoFrame(\n\tapiCtx context.Context, parsedSelector *Selector, frameNavIndex int, opts *FrameWaitForSelectorOptions,\n) (*Frame, string, error) {\n\t// Split selector at frame navigation boundary\n\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}","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/element_handle.go#L625-L661","documentation":"stepIntoFrame() resolves the iframe part of a frame-crossing selector (e.g. 'iframe >> button') by waiting for the iframe element; this error wraps that wait failing — almost always a timeout waiting for the iframe element to attach, or a strict-mode violation when several elements match.","triggerScenarios":"elementHandle.waitForSelector()/query with a frame-crossing selector where the iframe element does not appear within opts.Timeout, matches multiple elements (Strict is forced true here), or the wait itself errors.","commonSituations":"Slow-loading or dynamically injected iframes; selector matching a wrapper instead of the iframe; ad/analytics iframes appearing late; default timeout too short for heavy pages.","solutions":["Increase the timeout option for the wait","Verify the iframe part of the selector matches exactly one element","Wait for the iframe to exist/load before querying inside it","Prefer page.frameLocator() which re-resolves the frame chain robustly"],"exampleFix":"// before\nawait handle.waitForSelector('iframe >> .btn', { timeout: 1000 }); // finding iframe with selector\n\n// after\nawait handle.waitForSelector('iframe >> .btn', { timeout: 30000 });\n// or use the frame API:\nconst fl = page.frameLocator('#myframe');\nawait fl.locator('.btn').click();","handlingStrategy":"retry","validationCode":"// Verify the iframe exists (and is unique) before crossing into it\nconst frames = await page.$$('iframe[src*=\"example\"]');\nif (frames.length !== 1) throw new Error(`expected 1 iframe, got ${frames.length}`);","typeGuard":null,"tryCatchPattern":"try {\n  await handle.waitForSelector('iframe >> .btn', { timeout: 30000 });\n} catch (e) {\n  if (String(e).includes('finding iframe with selector')) {\n    await sleep(1000); // let the iframe attach, then retry\n    await handle.waitForSelector('iframe >> .btn', { timeout: 30000 });\n  } else { throw e; }\n}","preventionTips":["Give frame-crossing queries generous timeouts","Make iframe selectors unique — strict mode is enforced internally","Prefer page.frameLocator() over hand-built 'iframe >> sel' strings"],"tags":["browser","iframe","selector","timeout"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}