grafana/k6 · error

cannot do key up: %w

Error message

cannot do key up: %w

What it means

Returned by comboPress when the key-up leg fails. All key-downs already succeeded and were dispatched; the up leg replays the segments in reverse order, and this error wraps the first failing up(). Because downs completed, a failure here can leave keys logically pressed in the page even though local pressedKeys tracking was updated.

Source

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

func (k *Keyboard) comboPress(keys string, opts KeyboardOptions) error {
	if opts.Delay > 0 {
		if err := wait(k.ctx, opts.Delay); err != nil {
			return err
		}
	}

	kk := split(keys)
	for _, key := range kk {
		if err := k.down(key); err != nil {
			return fmt.Errorf("cannot do key down: %w", err)
		}
	}

	for i := range kk {
		key := kk[len(kk)-i-1]
		if err := k.up(key); err != nil {
			return fmt.Errorf("cannot do key up: %w", err)
		}
	}

	return nil
}

// This splits the string on `+`.
// If `+` on it's own is passed, it will return ["+"].
// If `++` is passed in, it will return ["+", ""].
// If `+++` is passed in, it will return ["+", "+"].
func split(keys string) []string {
	var (
		kk = make([]string, 0)
		s  strings.Builder
	)
	for _, r := range keys {
		if r == '+' && s.Len() > 0 {
			kk = append(kk, s.String())

View on GitHub (pinned to 93accf6570)

Solutions

  1. Trigger combos on elements that do not navigate mid-combo, or expect and handle the failure
  2. After this error, re-send press() of the same combo on a live page to clear stuck modifiers
  3. Use element.press() which sequences correctly with the page lifecycle
  4. Raise timeouts if the wrapped cause is DeadlineExceeded

Example fix

// before
await page.keyboard.press('Control+Enter'); // Enter submits & navigates, up-leg fails

// after
await page.$('#submit').click();           // navigate explicitly
await page.keyboard.press('Control+S');    // combos that do not navigate
Defensive patterns

Strategy: try-catch

Validate before calling

if (page.isClosed()) throw new Error('page closed before combo');
if (!isValidCombo(combo)) throw new Error(`invalid combo: ${combo}`);

Try / catch

try {
  await page.keyboard.press(combo);
} catch (e) {
  if (/cannot do key up/.test(e.message) && !page.isClosed()) {
    await page.keyboard.press(combo); // downs done, ups failed: re-run to clear stuck keys
  } else throw e;
}

Prevention

When it happens

Trigger: press('Control+A') where the page closes or navigates between the down leg and the up leg; renderer crash mid-combo; an up() validation failure for a segment that down() accepted with a different resolution.

Common situations: Combos that trigger navigation on key-down (e.g. Enter submitting a form) so the key-up lands on a dead or changed target.

Related errors


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