grafana/k6 · error
getting iframe frame
Error message
getting iframe frame: %w
What it means
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).
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
Example fix
// before
await page.locator('iframe#widget >> button').click();
// after
await page.waitForFrame({ name: 'widget' });
const frame = page.frame({ name: 'widget' });
await frame.locator('button').click(); Defensive patterns
Strategy: validation
Validate before calling
const el = await page.$('iframe#widget');
const tag = await el.evaluate((n) => n.tagName);
if (tag !== 'IFRAME') throw new Error(`selector matched <${tag}>, not an iframe`); Type guard
async function isIframeHandle(el) {
return (await el.evaluate((n) => n.tagName)) === 'IFRAME';
} Try / catch
try {
const frame = await el.contentFrame();
} catch (e) {
if (/getting iframe frame/.test(String(e))) {
await page.waitForFrame({ url: /widget/ });
const frame = await (await page.$('iframe#widget')).contentFrame();
} else throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- can't fetch the page for unknown reason
- creating a new
- element is not an iframe
- Error while parsing selector
- frame has been detached
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18).
Data as JSON: /api/errors/5105f8d807e70139.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:654
beforeFrame, afterFrame := h.splitSelectorAtFrame(parsedSelector, frameNavIndex)
// Find the iframe element using the "before frame" selector
iframeSelector := h.reconstructSelector(beforeFrame)
iframeHandle, err := h.waitForSelector(apiCtx, iframeSelector, opts)
if err != nil {
return nil, "", fmt.Errorf("finding iframe with selector %q: %w", iframeSelector, err)
}
// This is a valid response from waitForSelector. It means that the element
// was either hidden or detached.
if iframeHandle == nil {
return nil, "", ErrElementNotVisible
}
frame, err := iframeHandle.ContentFrame()
if err != nil {
return nil, "", fmt.Errorf("getting iframe frame: %w", err)
}
// Wait for selector in the iframe using the "after frame" selector
afterFrameSelector := h.reconstructSelector(afterFrame)
return frame, afterFrameSelector, nil
}
func (h *ElementHandle) waitForSelector(
apiCtx context.Context, selector string, opts *FrameWaitForSelectorOptions,
) (*ElementHandle, error) {
parsedSelector, err := NewSelector(selector)
if err != nil {
return nil, err
}
// Check for frame navigation in the selector
frameNavIndex := h.findFrameNavigationIndex(parsedSelector)View on GitHub (pinned to 3fcf5388d7)