grafana/k6 · error

sending key down: %w

Error message

sending key down: %w

What it means

Top-level wrapper returned by Keyboard.Down when the private k.down() fails. It aggregates two distinct failure modes: the key name is not valid for the active keyboard layout (validation error), or the CDP Input.dispatchKeyEvent(KeyDown) call fails (protocol/transport error).

Source

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

	layoutName    string // us by default
	layout        keyboardlayout.KeyboardLayout
}

// NewKeyboard returns a new keyboard with a "us" layout.
func NewKeyboard(ctx context.Context, s session) *Keyboard {
	return &Keyboard{
		ctx:         ctx,
		session:     s,
		pressedKeys: make(map[int64]struct{}),
		layoutName:  "us",
		layout:      keyboardlayout.GetKeyboardLayout("us"),
	}
}

// Down sends a key down message to a session target.
func (k *Keyboard) Down(key string) error {
	if err := k.down(key); err != nil {
		return fmt.Errorf("sending key down: %w", err)
	}
	return nil
}

// Up sends a key up message to a session target.
func (k *Keyboard) Up(key string) error {
	if err := k.up(key); err != nil {
		return fmt.Errorf("sending key up: %w", err)
	}
	return nil
}

// Press sends a key press message to a session target.
// It delays the action if `Delay` option is specified.
// A press message consists of successive key down and up messages.
func (k *Keyboard) Press(key string, kbdOpts KeyboardOptions) error {
	if err := k.comboPress(key, kbdOpts); err != nil {
		return fmt.Errorf("pressing key: %w", err)

View on GitHub (pinned to 93accf6570)

Solutions

  1. Use exact US-layout key names: 'Enter', 'Backspace', 'ArrowLeft', 'a', 'F1', single characters
  2. Ensure the page and browser are still open before sending key events
  3. For non-US characters use insertText() or type() which falls back to text insertion
  4. Catch the error and check the inner message to distinguish invalid-key from transport failure

Example fix

// before
await page.keyboard.down('Return');

// after
await page.keyboard.down('Enter');
Defensive patterns

Strategy: validation

Validate before calling

const VALID = new Set(['Enter','Backspace','Delete','Tab','Escape','ArrowUp','ArrowDown','ArrowLeft','ArrowRight','Home','End','PageUp','PageDown','Control','Shift','Alt','Meta',' ']);
function isValidKey(k) {
  return VALID.has(k) || /^[a-zA-Z0-9]$/.test(k) || /^F([1-9]|1[0-2])$/.test(k);
}
if (!isValidKey(key)) throw new Error(`invalid key: ${key}`);

Type guard

function isValidKey(k) {
  const VALID = new Set(['Enter','Backspace','Tab','Escape','ArrowUp','ArrowDown','ArrowLeft','ArrowRight','Home','End','PageUp','PageDown','Control','Shift','Alt','Meta']);
  return VALID.has(k) || /^[a-zA-Z0-9]$/.test(k) || /^F([1-9]|1[0-2])$/.test(k);
}

Try / catch

try {
  await page.keyboard.down(key);
} catch (e) {
  if (/not a valid key/.test(e.message)) throw new Error(`bad key name: ${key} (use US-layout names like 'Enter')`);
  throw e;
}

Prevention

When it happens

Trigger: keyboard.down('Return') or keyboard.down('é') — names absent from the default 'us' layout's ValidKeys; keyboard.down('Enter') after the page or browser was closed, so the CDP session rejects the event.

Common situations: Using OS-specific or X11 key names (Return, Backspace aliases) instead of the browser's US-layout names; pressing keys after page.close(); target crashed mid-interaction.

Related errors


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