grafana/k6 · error
tapping element
Error message
tapping element: %w
What it means
Thrown by the k6 browser module's ElementHandle.tap(). It wraps the whole pointer-action pipeline: scrolling the element into view, actionability checks (visible/stable/enabled), computing the tap point, hit-target verification, and finally Touchscreen.tap at the page level. Any stage failure — timeout, detached element, or 'another element is intercepting pointer action' (error:intercept) — surfaces wrapped in this message.
Solutions
- Launch the browser with touch enabled: const context = await browser.newContext({ hasTouch: true, viewport: { width: 390, height: 844 } }) and prefer page.tap or locator-based tap.
- Dismiss blocking overlays first (cookie banner, modal) or wait for them to disappear before tapping.
- Increase the timeout: el.tap({ timeout: '60s' }).
- Use { position: { x, y } } to tap a part of the element not covered by the overlay, or { force: true } as a last resort.
- Re-query the element to get a fresh attached handle.
Example fix
// before
const el = await page.$('#menu-item');
await el.tap(); // intercepting overlay or no touch emulation
// after
const context = await browser.newContext({ hasTouch: true, viewport: { width: 390, height: 844 } });
const page = await context.newPage();
await page.click('#cookie-accept', { timeout: '5s' }).catch(() => {});
const el = await page.waitForSelector('#menu-item', { state: 'visible' });
await el.tap({ timeout: '30s' }); Defensive patterns
Strategy: try-catch
Validate before calling
const context = await browser.newContext({ hasTouch: true, viewport: { width: 390, height: 844 } });
const visible = await el.isVisible().catch(() => false);
if (visible) { await el.tap({ timeout: '30s' }); } Try / catch
try {
await el.tap({ timeout: '30s' });
} catch (e) {
if (String(e).includes('intercept')) {
await page.click('#cookie-accept').catch(() => {});
await el.tap({ timeout: '30s' });
} else { throw e; }
} Prevention
- Create the context with hasTouch:true before scripting tap flows.
- Dismiss known overlays (cookie banners, chat widgets) at test start as a standard step.
- Prefer page.tap/locator APIs over raw ElementHandle so auto-waiting applies.
When it happens
Trigger: Calling el.tap() when the browser context was launched without touch support enabled (hasTouch not set), so tap events misbehave; an overlay (cookie banner, modal backdrop) covering the element; element hidden/animating past the timeout; element detached by rerender.
Common situations: Testing mobile flows on a desktop-launched context without the hasTouch browser option; cookie-consent or chat-widget overlays intercepting the tap point; sticky headers covering the target after scroll.
Related errors
- tapping on
- parsing element tap options
- scrolling element into view
- scrolling element into view
- selecting text
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18).
Data as JSON: /api/errors/5b1b1ac1f1ee4842.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/element_handle.go:1509
if !ok {
return fmt.Errorf("unexpected type %T", result)
}
if v != "done" {
return errorFromDOMError(v)
}
return nil
}
// Tap scrolls element into view and taps in the center of the element.
func (h *ElementHandle) Tap(opts *ElementHandleTapOptions) error {
tap := func(apiCtx context.Context, handle *ElementHandle, p *Position) (any, error) {
return nil, handle.tap(apiCtx, p)
}
tapAction := h.newPointerAction(tap, &opts.ElementHandleBasePointerOptions)
if _, err := call(h.ctx, tapAction, opts.Timeout); err != nil {
return fmt.Errorf("tapping element: %w", err)
}
applySlowMo(h.ctx)
return nil
}
func (h *ElementHandle) tap(_ context.Context, p *Position) error {
return h.frame.page.Touchscreen.tap(p.X, p.Y)
}
// TextContent returns the text content of the element.
// The second return value is true if the text content exists, and false otherwise.
func (h *ElementHandle) TextContent() (string, bool, error) {
textContent := func(apiCtx context.Context, handle *ElementHandle) (any, error) {
return handle.textContent(apiCtx)
}
opts := NewElementHandleBaseOptions(h.DefaultTimeout())View on GitHub (pinned to 3fcf5388d7)