grafana/k6 · error

checking hit target: %w

Error message

checking hit target: %w

What it means

Final actionability gate of pointer actions (non-force): checkHitTargetAt ran the injected hit-target check at the computed point and returned false — meaning another element intercepts pointer events there ('error:intercept' → 'another element is intercepting with pointer action'), or the check/its recursive frame walk errored. Note a message quirk: when the check returns false with a nil error, %w renders '%!w(<nil>)', which still means interception.

Source

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

		} 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)
		if res, err = fn(apiCtx, h, p); err != nil {
			return nil, fmt.Errorf("evaluating pointer action: %w", err)
		}
		// Do we need to wait for navigation to happen
		if !opts.NoWaitAfter {
			if err = b.Wait(apiCtx); err != nil {
				return nil, fmt.Errorf("waiting for navigation: %w", err)

View on GitHub (pinned to 93accf6570)

Solutions

  1. Dismiss or wait out the covering element first (accept the banner, wait for the spinner to disappear)
  2. If interception is expected/harmless, skip the check with force: el.click({ force: true })
  3. Scroll the target fully into view so sticky headers do not overlap it, or click at a position clear of the overlay
  4. Set an adequate timeout so the retry loop can wait for the overlay to close

Example fix

// before
page.$('#submit').click(); // spinner overlay intercepts

// after
page.waitForSelector('.spinner', { state: 'hidden', timeout: '20s' });
page.$('#submit').click();
Defensive patterns

Strategy: validation

Validate before calling

const overlay = page.$('.modal-backdrop, .cookie-banner, .spinner');
if (overlay && overlay.isVisible()) {
  page.waitForSelector('.modal-backdrop, .cookie-banner, .spinner', { state: 'hidden', timeout: '20s' });
}
el.click();

Try / catch

try {
  el.click();
} catch (e) {
  const msg = String(e);
  if (msg.includes('checking hit target') || msg.includes('intercepting')) {
    el.click({ force: true }); // interception is expected/harmless
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Overlay, modal backdrop, cookie banner, sticky header, or toast covering the target point; element moved between point computation and hit test; nested iframe interception checks failing because a frame navigated.

Common situations: Autoplaying cookie/consent dialogs on EU pages; fixed footers overlapping content on small viewports; tooltips appearing on hover and covering the button; spinner overlays during async saves.

Related errors


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