grafana/k6 · error

parsing frame tap options

Error message

parsing frame tap options: %w

What it means

Thrown by the k6 browser module ('k6/browser') while converting the JS options object of frame.tap(selector, options) into the Go FrameTapOptions (browser/frame_mapping.go:384). FrameTapOptions.Parse delegates to ElementHandleBasePointerOptions.Parse, which requires position to export to a numeric x/y map, and then parses modifiers via rt.ExportTo into []string; either conversion failure is wrapped with this message. plain values like timeout/strict/force/trial are coerced and cannot fail.

Solutions

  1. Make modifiers an array of strings: modifiers: ['Alt', 'Shift']
  2. Give position as an object with numeric fields: position: { x: 10, y: 20 }
  3. Remove the offending option to fall back to defaults (timeout defaults to the frame/page timeout)
  4. Wrap dynamic option objects in Number()/Array.isArray() normalization before passing them

Example fix

// before
frame.tap('#btn', { modifiers: 'Shift', position: [10, 20] });
// after
frame.tap('#btn', { modifiers: ['Shift'], position: { x: 10, y: 20 } });
Defensive patterns

Strategy: validation

Validate before calling

const ok = (o = {}) =>
  (o.modifiers == null || (Array.isArray(o.modifiers) && o.modifiers.every(m => typeof m === 'string'))) &&
  (o.position == null || (typeof o.position === 'object' &&
    typeof o.position.x === 'number' && typeof o.position.y === 'number'));
if (!ok(opts)) throw new Error('invalid tap options');

Type guard

function isTapOptions(o) {
  if (o == null) return true;
  if (typeof o !== 'object' || Array.isArray(o)) return false;
  if (o.modifiers != null && !(Array.isArray(o.modifiers) && o.modifiers.every(m => typeof m === 'string'))) return false;
  if (o.position != null && !(typeof o.position.x === 'number' && typeof o.position.y === 'number')) return false;
  return true;
}

Try / catch

try { frame.tap(sel, opts); } catch (e) { if (!String(e.message).startsWith('parsing frame tap options')) throw e; /* normalize options and retry once */ }

Prevention

When it happens

Trigger: frame.tap('#btn', { modifiers: 'Shift' }) (string instead of array); frame.tap('#btn', { position: [10, 20] }) or { position: 'center' } (position must be an object { x: number, y: number }). Same options reach this path via FrameLocator.tap and page taps on mobile emulation.

Common situations: Porting Playwright TypeScript scripts where an array or shorthand was used for position; building options dynamically from JSON.parse or environment variables so numbers arrive as strings; assuming Playwright accepts the same shapes k6 does.

Related errors


AI-assisted analysis of grafana/k6@8d06114777 (2026-09-14). Data as JSON: /api/errors/b98db6c346d8f709. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/browser/frame_mapping.go:382

		"setInputFiles": func(selector string, files sobek.Value, opts sobek.Value) (*sobek.Promise, error) {
			popts, err := parseFrameSetInputFilesOptions(rt, opts, f.Timeout())
			if err != nil {
				return nil, fmt.Errorf("parsing setInputFiles options: %w", err)
			}

			pfiles := new(common.Files)
			if err := pfiles.Parse(vu.Context(), files); err != nil {
				return nil, fmt.Errorf("parsing setInputFiles parameter: %w", err)
			}

			return promise(vu, func() (any, error) {
				return nil, f.SetInputFiles(selector, pfiles, popts) //nolint:wrapcheck
			}), nil
		},
		"tap": func(selector string, opts sobek.Value) (*sobek.Promise, error) {
			popts, err := parseFrameTapOptions(rt, opts, f.Timeout())
			if err != nil {
				return nil, fmt.Errorf("parsing frame tap options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return nil, f.Tap(selector, popts) //nolint:wrapcheck
			}), nil
		},
		"textContent": func(selector string, opts sobek.Value) (*sobek.Promise, error) {
			popts, err := parseFrameTextContentOptions(rt, opts, f.Timeout())
			if err != nil {
				return nil, fmt.Errorf("parsing text content options: %w", err)
			}

			return promise(vu, func() (any, error) {
				s, ok, err := f.TextContent(selector, popts)
				if err != nil {
					return nil, err //nolint:wrapcheck
				}
				if !ok {
					return nil, nil //nolint:nilnil

View on GitHub (pinned to 8d06114777)