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

  1. Pass an object with a numeric delay in milliseconds: { delay: 100 }, or omit options
  2. Convert dynamic values: { delay: Number(cfg.delay) }
  3. Never pass a plain string as the options argument
  4. 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

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


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)