grafana/k6 · error

pointer action: %w

Error message

pointer action: %w

What it means

Pointer actions without an explicit position call clickablePoint, which takes the element's bounding box and returns its center. Failure means BoundingBox errored ('finding clickable point' — element hidden, detached, or cross-origin layout failure) or produced no usable box. Effectively: the element has no clickable center because it is not rendered with size.

Source

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

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

View on GitHub (pinned to 93accf6570)

Solutions

  1. Wait until the element has size: waitForSelector(sel, { state: 'visible' }) plus an optional boundingBox() size check
  2. Fix the page CSS in test mode so the control has non-zero dimensions
  3. Re-query the element right before the click to avoid stale handles
  4. If only the event matters, el.dispatchEvent('click') bypasses pointer geometry entirely

Example fix

// before
page.$('#icon-btn').click(); // zero-size icon until font loads

// after
const el = page.waitForSelector('#icon-btn', { state: 'visible' });
if (el.boundingBox()) el.click();
Defensive patterns

Strategy: validation

Validate before calling

const el = page.waitForSelector('#icon-btn', { state: 'visible' });
const b = el.boundingBox();
if (!b || (b.width === 0 && b.height === 0)) {
  throw new Error('element has zero size; give it dimensions before clicking');
}
el.click();

Try / catch

try {
  el.click();
} catch (e) {
  if (String(e).includes('pointer action')) {
    // no clickable center: fall back to a raw event
    el.dispatchEvent('click');
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Element with zero width/height (empty inline spans, collapsed flex items); display:none ancestors; element detached between actionability check and point computation; bounding-box call failing across a swapping cross-origin iframe.

Common situations: Icon buttons that only get size after a webfont/CSS loads; placeholders rendered empty until data arrives; components collapsed by default CSS in test builds.

Related errors


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