grafana/k6 · error

getting iframe frame: %w

Error message

getting iframe frame: %w

What it means

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 ...'.

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 93accf6570)

Solutions

  1. Tighten the iframe selector so it matches the <iframe> element itself
  2. Retry after the iframe content settles (wait for a known element inside it)
  3. Increase the timeout
  4. Use page.frameLocator() instead of hand-built frame-crossing selectors

Example fix

// before
await handle.waitForSelector('#container >> button'); // matched a div, not the iframe

// after
await handle.waitForSelector('#container iframe >> button');
Defensive patterns

Strategy: try-catch

Validate before calling

const isIframe = await handle.evaluate((el) => el.tagName === 'IFRAME');
if (!isIframe) throw new Error('selector must resolve to an iframe');

Try / catch

try {
  await handle.waitForSelector('iframe >> .btn');
} catch (e) {
  if (String(e).includes('getting iframe frame')) {
    // matched node wasn't an iframe or it was swapped; tighten selector and retry
    await handle.waitForSelector('#real-iframe >> .btn');
  } else { throw e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/5105f8d807e70139. Report an issue: GitHub.