grafana/k6 · error
parsing keyboard options
Error message
parsing keyboard options: %w
What it means
Thrown by keyboard.press(key, options) (browser/keyboard_mapping.go:26) when the options value cannot be exported to Go's KeyboardOptions { Delay int64 } via rt.ExportTo. Unlike most frame options, this path is a strict typed export: it fails when opts is not an object at all (a string like 'fast') or when delay is not a number (e.g. '100ms', 'fast', or a numeric string '100').
Solutions
- Pass an object with a numeric delay in milliseconds: { delay: 100 }, or omit options
- Convert dynamic values: { delay: Number(cfg.delay) }
- Never pass a plain string as the options argument
- If you need default behavior, call press(key) with no second argument
Example fix
// before
page.keyboard.press('Enter', { delay: '100ms' });
// after
page.keyboard.press('Enter', { delay: 100 }); Defensive patterns
Strategy: type-guard
Validate before calling
if (opts !== undefined && (typeof opts !== 'object' || Array.isArray(opts) ||
(opts.delay !== undefined && typeof opts.delay !== 'number'))) {
throw new Error('keyboard options must be { delay: number }');
} Type guard
function isKeyboardOptions(o) {
return o === undefined || o === null ||
(typeof o === 'object' && !Array.isArray(o) &&
(o.delay === undefined || (typeof o.delay === 'number' && Number.isFinite(o.delay))));
} Try / catch
try { await page.keyboard.press('Enter', { delay: Number(cfg.delay) }); } catch (e) { if (!String(e.message).includes('parsing keyboard options')) throw e; } Prevention
- delay is a bare number in milliseconds — never '100ms' or 'fast'
- Never pass a string as the second argument to keyboard.press
- Convert config-sourced delays with Number() at load time
When it happens
Trigger: page.keyboard.press('Enter', 'fast'); page.keyboard.press('Enter', { delay: '100ms' }); page.keyboard.press('Enter', { delay: '100' }) on this strict export path; opts loaded from JSON where delay is a string.
Common situations: Porting Playwright snippets that name delays with units; storing press options in shared config and forgetting to convert to a number; passing a leftover string argument (e.g. a key name) as the second parameter.
Related errors
- parse press options of selector
- parsing frame tap options
- parsing type options
- frame waitForFunction
- parsing check options
AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18).
Data as JSON: /api/errors/e3b6b44ecf861ef5.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/browser/keyboard_mapping.go:26
"go.k6.io/k6/v2/internal/js/modules/k6/browser/common"
)
func mapKeyboard(vu moduleVU, kb *common.Keyboard) mapping {
return mapping{
"down": func(key string) *sobek.Promise {
return promise(vu, func() (any, error) {
return nil, kb.Down(key) //nolint:wrapcheck
})
},
"up": func(key string) *sobek.Promise {
return promise(vu, func() (any, error) {
return nil, kb.Up(key) //nolint:wrapcheck
})
},
"press": func(key string, opts sobek.Value) (*sobek.Promise, error) {
kbopts, err := exportTo[common.KeyboardOptions](vu.Runtime(), opts)
if err != nil {
return nil, fmt.Errorf("parsing keyboard options: %w", err)
}
return promise(vu, func() (any, error) {
return nil, kb.Press(key, kbopts)
}), nil
},
"type": func(text string, opts sobek.Value) (*sobek.Promise, error) {
kbopts, err := exportTo[common.KeyboardOptions](vu.Runtime(), opts)
if err != nil {
return nil, fmt.Errorf("parsing keyboard options: %w", err)
}
return promise(vu, func() (any, error) {
return nil, kb.Type(text, kbopts)
}), nil
},
"insertText": func(text string) *sobek.Promise {
return promise(vu, func() (any, error) {
return nil, kb.InsertText(text) //nolint:wrapcheck
})View on GitHub (pinned to 01ffac6f24)