grafana/k6 · error
dispatching locator event %q to %q: %w
Error message
dispatching locator event %q to %q: %w
What it means
Thrown by Locator.DispatchEvent() when the wrapped frame.dispatchEvent call fails. Strict mode is forced on, so the selector must resolve to exactly one element. Typical failures: strict-mode violation, timeout waiting for the element, or the element's execution context being destroyed (navigation) while the event was dispatched.
Source
Thrown at internal/js/modules/k6/browser/common/locator.go:638
return fmt.Errorf("tapping on %q: %w", l.selector, err)
}
applySlowMo(l.ctx)
return nil
}
// DispatchEvent dispatches an event for the element matching the
// locator's selector with strict mode on.
func (l *Locator) DispatchEvent(typ string, eventInit any, opts *FrameDispatchEventOptions) error {
l.log.Debugf(
"Locator:DispatchEvent", "fid:%s furl:%q sel:%q typ:%q eventInit:%+v opts:%+v",
l.frame.ID(), l.frame.URL(), l.selector, typ, eventInit, opts,
)
opts.Strict = true
if err := l.frame.dispatchEvent(l.selector, typ, eventInit, opts); err != nil {
return fmt.Errorf("dispatching locator event %q to %q: %w", typ, l.selector, err)
}
applySlowMo(l.ctx)
return nil
}
// WaitFor waits for the element matching the locator's selector with strict mode on.
func (l *Locator) WaitFor(opts *FrameWaitForSelectorOptions) error {
l.log.Debugf("Locator:WaitFor", "fid:%s furl:%q sel:%q opts:%+v", l.frame.ID(), l.frame.URL(), l.selector, opts)
opts.Strict = true
_, err := l.frame.waitFor(l.selector, opts, 20)
if err != nil {
return fmt.Errorf("waiting for %q: %w", l.selector, err)
}
return nilView on GitHub (pinned to 93accf6570)
Solutions
- Use a unique selector that matches exactly one element
- await locator.waitFor() before dispatching
- Re-dispatch after navigation/SPA transitions complete (element handles do not survive re-render)
- Increase opts.timeout on slow pages
Example fix
// before
await page.locator('.item').dispatchEvent('click'); // matches many items
// after
await page.locator('.item[data-id="42"]').waitFor();
await page.locator('.item[data-id="42"]').dispatchEvent('click'); Defensive patterns
Strategy: try-catch
Validate before calling
const els = await page.$$(sel);
if (els.length !== 1) throw new Error(`selector matches ${els.length} elements`);
await page.locator(sel).dispatchEvent('click'); Type guard
async function isAttached(page, sel) {
const el = await page.$(sel);
return el !== null;
} Try / catch
try {
await page.locator(sel).dispatchEvent('click', { bubbles: true });
} catch (e) {
if (/timeout|strict mode/i.test(e.message)) {
await page.locator(sel).waitFor();
await page.locator(sel).dispatchEvent('click', { bubbles: true });
} else throw e;
} Prevention
- Use unique selectors before dispatching synthetic events
- Prefer locator.click() over dispatchEvent('click') when possible — it retries
- Re-query locators after SPA route changes; never cache handles across renders
When it happens
Trigger: locator.dispatchEvent(type, eventInit) where the selector matches 0 or >1 elements; the page navigates between resolving the element and dispatching, destroying the context; the element is detached from the DOM past the timeout.
Common situations: Dispatching 'click' or 'input' events to trigger SPA handlers on elements rendered late; selectors matching both a parent and child; dispatching during a client-side route transition that re-renders the tree.
Related errors
- getting input value of %q: %w
- selecting option on %q: %w
- pressing %q on %q: %w
- hovering on %q: %w
- tapping on %q: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/36e7a4db96595e5d.
Report an issue: GitHub.