grafana/k6 · error

dispatching key event up: %w

Error message

dispatching key event up: %w

What it means

Thrown by Keyboard.up() when the CDP Input.dispatchKeyEvent(KeyUp) action fails after validation passed. The modifier state and pressedKeys map are already updated before dispatch, so on failure the tracked modifier bit for the key has been cleared locally even though no key-up reached the page — later events may carry wrong modifiers if the session survives.

Source

Thrown at internal/js/modules/k6/browser/common/keyboard.go:160

	keyInput := keyboardlayout.KeyInput(key)
	if _, ok := k.layout.ValidKeys[keyInput]; !ok {
		return fmt.Errorf("'%s' is not a valid key for layout '%s'", key, k.layoutName)
	}

	keyDef := k.keyDefinitionFromKey(keyInput)
	k.modifiers &= ^k.modifierBitFromKeyName(keyDef.Key)
	k.pressedKeysMu.Lock()
	delete(k.pressedKeys, keyDef.KeyCode)
	k.pressedKeysMu.Unlock()

	action := input.DispatchKeyEvent(input.KeyUp).
		WithModifiers(input.Modifier(k.modifiers)).
		WithKey(keyDef.Key).
		WithWindowsVirtualKeyCode(keyDef.KeyCode).
		WithCode(keyDef.Code).
		WithLocation(keyDef.Location)
	if err := action.Do(cdp.WithExecutor(k.ctx, k.session)); err != nil {
		return fmt.Errorf("dispatching key event up: %w", err)
	}

	return nil
}

func (k *Keyboard) insertText(text string) error {
	action := input.InsertText(text)
	if err := action.Do(cdp.WithExecutor(k.ctx, k.session)); err != nil {
		return fmt.Errorf("inserting text: %w", err)
	}
	return nil
}

func (k *Keyboard) keyDefinitionFromKey(key keyboardlayout.KeyInput) keyboardlayout.KeyDefinition {
	shift := k.modifiers & ModifierKeyShift

	// Find directly from the keyboard layout
	srcKeyDef, ok := k.layout.Keys[key]

View on GitHub (pinned to 93accf6570)

Solutions

  1. Keep down()/up() adjacent; use press() for atomic pairs
  2. Check page.isClosed() before up()
  3. On failure in a surviving session, send a fresh down/up press() to resynchronize modifier state
  4. Raise the timeout if DeadlineExceeded is the wrapped cause

Example fix

// before
await page.keyboard.down('Shift');
await page.goto(url);              // navigation between the pair
await page.keyboard.up('Shift');

// after
await page.goto(url);
await page.keyboard.press('Shift+F10'); // atomic combo after navigation
Defensive patterns

Strategy: try-catch

Validate before calling

if (page.isClosed()) throw new Error('page closed before key up');

Try / catch

try {
  await page.keyboard.up(key);
} catch (e) {
  if (/dispatching key event up/.test(e.message) && !page.isClosed()) {
    await page.keyboard.press(key); // resync modifier state after failed up
  } else throw e;
}

Prevention

When it happens

Trigger: up('Shift') after the page closed between down and up; target crash before the key-up; context canceled by a timeout exactly between the paired events.

Common situations: down/up pairs straddling an await that navigates or closes the page; long-running hold-key interactions under tight timeouts.

Related errors


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