grafana/k6 · error

translating point to page

Error message

translating point to page: %w

What it means

Stage of the k6 browser module's pointer-action pipeline for elements inside iframes: translatePointToPage converts the click/tap point from frame-relative to page-relative coordinates when the owning frame has a parent. This error wraps failure of that translation: resolving the owner frame, getting the iframe's FrameElement, or reading that frame element's BoundingBox failed (frame navigated/closed, cross-origin frame access limits, or detached frame element).

Solutions

  1. Re-acquire the frame chain before acting: page.frame(...) or waitForSelector inside the frame, so owner frames are live.
  2. Wait for the iframe itself to be visible and settled: ensure the iframe element has a bounding box before acting on its content.
  3. Retry the action once — iframe navigation races are often transient.
  4. If the widget navigates predictably (e.g., after an inner click), pair the trigger with waitForNavigation on the frame.

Example fix

// before
const frame = page.frames().find(f => f.name() === 'widget');
const el = await frame.$('#pay');
await el.click(); // widget iframe reloaded mid-action -> translation fails

// after
await page.waitForSelector('iframe[name="widget"]', { state: 'visible' });
const frame = page.frames().find(f => f.name() === 'widget');
const el = await frame.waitForSelector('#pay', { state: 'visible' });
await el.click();
Defensive patterns

Strategy: retry

Validate before calling

const frameEl = await page.waitForSelector('iframe[name="widget"]', { state: 'visible', timeout: '30s' });
const box = await frameEl.boundingBox();
if (!box) { throw new Error('iframe has no bounding box; skip in-frame action'); }
const frame = page.frames().find(f => f.name() === 'widget');
const el = await frame.waitForSelector(sel, { state: 'visible' });
await el.click();

Try / catch

for (let i = 0; i < 2; i++) {
  try { await el.click(); break; }
  catch (e) {
    if (i === 1 || !String(e).includes('translating point to page')) throw e;
    // iframe may have navigated: rebuild the frame chain and handle
    const frame = page.frames().find(f => f.name() === frameName);
    el = await frame.waitForSelector(sel, { state: 'visible' });
  }
}

Prevention

When it happens

Trigger: click()/tap() on elements inside an iframe whose document navigates or is removed between the state checks and the translation; iframes whose bounding box cannot be resolved (hidden iframe, display:none container); nested iframe hierarchies where an intermediate frame detaches.

Common situations: Payment/ad/auth widgets embedded in iframes that reload on their own schedule; tests acting in an iframe right as the host page rerenders the iframe element; iframes hidden via CSS until user action.

Related errors


AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18). Data as JSON: /api/errors/d1fe663e297e7c13. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/common/element_handle.go:1759

		// Get the clickable point
		if p != nil {
			p, err = h.offsetPosition(apiCtx, opts.Position)
			if err != nil {
				return nil, fmt.Errorf("getting element position: %w", err)
			}
		} else {
			p, err = h.clickablePoint()
			if err != nil {
				return nil, fmt.Errorf("pointer action: %w", err)
			}
		}

		// Further translation of the point might be necessary if the point
		// is still relative to the parent frame it is in and not the page.
		*p, err = h.translatePointToPage(apiCtx, *p)
		if err != nil {
			return nil, fmt.Errorf("translating point to page: %w", err)
		}

		// Do a final actionability check to see if element can receive events
		// at mouse position in question
		if !opts.Force {
			if ok, err := h.checkHitTargetAt(apiCtx, *p); !ok {
				return nil, fmt.Errorf("checking hit target: %w", err)
			}
		}
		// Are we only "trialing" the action but not actually performing
		// it (ie. running the actionability checks).
		if opts.Trial {
			return nil, nil //nolint:nilnil
		}

		b := NewBarrier()
		h.frame.manager.addBarrier(b)
		defer h.frame.manager.removeBarrier(b)

View on GitHub (pinned to 3fcf5388d7)