grafana/k6 · error
key down: %w
Error message
key down: %w
What it means
Returned by Keyboard.press (the private single-key path used by typ()) when its key-down call fails. Distinct from comboPress: this presses exactly one key — wait(opts.Delay) first if set, then down(); the error wraps down()'s invalid-key validation or CDP dispatch failure. The subsequent up() error would surface unwrapped from press().
Source
Thrown at internal/js/modules/k6/browser/common/keyboard.go:313
kk = append(kk, s.String())
s.Reset()
} else {
s.WriteRune(r)
}
}
kk = append(kk, s.String())
return kk
}
func (k *Keyboard) press(key string, opts KeyboardOptions) error {
if opts.Delay > 0 {
if err := wait(k.ctx, opts.Delay); err != nil {
return err
}
}
if err := k.down(key); err != nil {
return fmt.Errorf("key down: %w", err)
}
return k.up(key)
}
func (k *Keyboard) typ(text string, opts KeyboardOptions) error {
layout := keyboardlayout.GetKeyboardLayout(k.layoutName)
for _, c := range text {
if opts.Delay > 0 {
if err := wait(k.ctx, opts.Delay); err != nil {
return err
}
}
keyInput := keyboardlayout.KeyInput(c)
if _, ok := layout.ValidKeys[keyInput]; ok {
if err := k.press(string(c), opts); err != nil {
return fmt.Errorf("pressing key: %w", err)
}
continueView on GitHub (pinned to 93accf6570)
Solutions
- Ensure page liveness before typing/pressing (page.isClosed())
- On failure, re-acquire the page state and restart the type() from a cleared input
- Check the wrapped error to distinguish invalid-key from transport failure
- Keep delays modest so fewer presses are in flight when timeouts hit
Example fix
// before
await page.close();
await page.keyboard.press('x');
// after
if (!page.isClosed()) {
await page.keyboard.press('x');
} Defensive patterns
Strategy: try-catch
Validate before calling
if (page.isClosed()) throw new Error('page closed before press');
if (!isValidKeyName(key)) throw new Error(`invalid key: ${key}`); Try / catch
try {
await page.keyboard.press(key, { delay });
} catch (e) {
if (/key down/.test(e.message) && /not a valid key/.test(e.message)) throw new Error(`bad key name: ${key}`);
if (/context|deadline/i.test(e.message)) throw new Error('timeout — lower delay or raise timeout option');
throw e;
} Prevention
- Validate key names before pressing
- Keep delay well under the remaining timeout budget
- Stop typing/pressing before closing pages or ending iterations
When it happens
Trigger: typ() pressing a character validated as a layout key but whose dispatch fails (page closed mid-type); direct press('x') on a dead target; delay canceled context surfaces as the bare wait error, not this one.
Common situations: Internal path hit while type() walks a string and the page dies partway; single-key press races with page teardown.
Related errors
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/f70f7c01e7f5511f.
Report an issue: GitHub.