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
- Keep down()/up() adjacent; use press() for atomic pairs
- Check page.isClosed() before up()
- On failure in a surviving session, send a fresh down/up press() to resynchronize modifier state
- 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
- Never navigate or close between down() and up()
- Use press() for atomic pairs
- After an up() failure, re-press the key to clear stuck modifiers
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.