grafana/k6 · error

clicking on x:%f y:%f: %w

Error message

clicking on x:%f y:%f: %w

What it means

Thrown by Mouse.Click(x, y) when the internal click sequence (move + N x down/up) fails at the CDP level. The mouse API targets raw viewport coordinates, not selectors, so failures are usually environmental: the page/context was closed or navigated mid-sequence, the browser target crashed, or the CDP Input.dispatchMouseEvent call was rejected.

Source

Thrown at internal/js/modules/k6/browser/common/mouse.go:39

	button          input.MouseButton
}

// NewMouse creates a new mouse.
func NewMouse(ctx context.Context, s session, f *Frame, ts *TimeoutSettings, k *Keyboard) *Mouse {
	return &Mouse{
		ctx:             ctx,
		session:         s,
		frame:           f,
		timeoutSettings: ts,
		keyboard:        k,
		button:          input.None,
	}
}

// Click will trigger a series of MouseMove, MouseDown and MouseUp events in the browser.
func (m *Mouse) Click(x float64, y float64, opts *MouseClickOptions) error {
	if err := m.click(x, y, opts); err != nil {
		return fmt.Errorf("clicking on x:%f y:%f: %w", x, y, err)
	}
	return nil
}

func (m *Mouse) click(x float64, y float64, opts *MouseClickOptions) error {
	mouseDownUpOpts := opts.ToMouseDownUpOptions()
	if err := m.move(x, y, NewMouseMoveOptions()); err != nil {
		return err
	}
	for i := 0; i < int(mouseDownUpOpts.ClickCount); i++ {
		if err := m.down(mouseDownUpOpts); err != nil {
			return err
		}
		if opts.Delay != 0 {
			t := time.NewTimer(time.Duration(opts.Delay) * time.Millisecond)
			select {
			case <-m.ctx.Done():
				t.Stop()

View on GitHub (pinned to 93accf6570)

Solutions

  1. Ensure the page and browser context are still open before dispatching (check page.isClosed())
  2. Recompute coordinates from a fresh element.boundingBox() immediately before clicking
  3. Scroll the element into view so coordinates land inside the viewport
  4. Wrap mouse calls in try/catch and re-locate after navigation

Example fix

// before
const box = await page.locator('#btn').boundingBox();
await page.goto(nextUrl);
await page.mouse.click(box.x + 5, box.y + 5); // stale coords, session churn

// after
await page.goto(nextUrl);
const box = await page.locator('#btn').boundingBox();
if (box) await page.mouse.click(box.x + 5, box.y + 5);
Defensive patterns

Strategy: try-catch

Validate before calling

if (page.isClosed()) throw new Error('page closed');
const box = await page.locator('#btn').boundingBox();
if (!box) throw new Error('element has no bounding box');
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);

Type guard

function isValidPoint(box, x, y) {
  return !!box && x >= 0 && y >= 0 && x <= box.width && y <= box.height;
}

Try / catch

try {
  await page.mouse.click(x, y);
} catch (e) {
  if (/closed|destroyed|target closed/i.test(e.message)) {
    throw new Error('page/session gone before click');
  }
  throw e;
}

Prevention

When it happens

Trigger: mouse.click(x, y) after page.close() or during navigation that destroys the session; coordinates far outside the viewport; browser process crash or DevTools session drop while dispatching.

Common situations: Clicking coordinates captured earlier from boundingBox() after the page re-rendered or navigated; using mouse after a timeout that closed the page; clicking beyond viewport bounds without scrolling.

Related errors


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