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 nil

View on GitHub (pinned to 93accf6570)

Solutions

  1. Use a unique selector that matches exactly one element
  2. await locator.waitFor() before dispatching
  3. Re-dispatch after navigation/SPA transitions complete (element handles do not survive re-render)
  4. 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

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


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