grafana/k6 · error

getting element position

Error message

getting element position: %w

What it means

Stage of the k6 browser module's pointer-action pipeline that runs when opts.Position is set: offsetPosition computes the absolute click/tap point from the user-supplied offset relative to the element. This error wraps that computation failing — typically because the element's bounding box could not be obtained (hidden, no layout, detached) or the containing element is not queryable.

Solutions

  1. Wait for the element to be visible and have a size: waitForSelector(sel, { state: 'visible' }) and confirm via el.boundingBox() in a retry loop if needed.
  2. Verify the offset lies within the element's current bounding box; recompute from el.boundingBox() rather than hardcoding.
  3. Set an explicit viewport matching the layout the offsets were designed for.
  4. Drop the custom position and click the center if the spot does not matter.

Example fix

// before
const el = await page.$('#map');
await el.click({ position: { x: 320, y: 240 } }); // map not rendered yet -> no box

// after
const el = await page.waitForSelector('#map', { state: 'visible' });
const box = await el.boundingBox();
if (box && box.width > 0) {
  await el.click({ position: { x: Math.min(320, box.width - 1), y: Math.min(240, box.height - 1) } });
}
Defensive patterns

Strategy: validation

Validate before calling

const box = await el.boundingBox();
if (!box || box.width <= 0 || box.height <= 0) {
  throw new Error('element has no rendered box; cannot use position offset');
}
const x = Math.min(offsetX, box.width - 1);
const y = Math.min(offsetY, box.height - 1);
await el.click({ position: { x, y } });

Type guard

async function hasUsableBox(el) {
  const b = await el.boundingBox().catch(() => null);
  return !!b && b.width > 0 && b.height > 0;
}

Try / catch

try {
  await el.click({ position: { x: offsetX, y: offsetY }, timeout: '30s' });
} catch (e) {
  if (String(e).includes('getting element position')) {
    await el.click(); // fall back to center click
  } else { throw e; }
}

Prevention

When it happens

Trigger: click({ position: { x: 10, y: 10 } }) or tap({ position }) on an element whose bounding box cannot be resolved at action time — display:none, zero-size, detached — or with offsets outside the element's box on a re-rendered node.

Common situations: Clicking a specific spot on a canvas/map/image that is lazily rendered or resized at action time; offsets tuned against a different viewport than the test's (responsive layouts shift coordinates).

Related errors


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

Appendix: source

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

			}
			err = h.scrollRectIntoViewIfNeeded(apiCtx, rect)
		} else {
			_, err = h.eval(
				apiCtx,
				evalOptions{forceCallable: true, returnByValue: false},
				js.ScrollIntoView,
				sopts,
			)
		}
		if err != nil {
			return nil, fmt.Errorf("scrolling element into view: %w", err)
		}

		// 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 {

View on GitHub (pinned to 3fcf5388d7)