grafana/k6 · error
parsing locator tap options: %w
Error message
parsing locator tap options: %w
What it means
Thrown when locator.tap(opts) fails to parse options into FrameTapOptions. Two strict export paths make this a live error: position must export to map[string]float64 (numeric {x, y}), and modifiers must export to []string — so tap({ modifiers: 'Shift' }) fails with 'parsing locator tap options: <export error>'. Note the default timeout here comes from DefaultTimeout(), not the locator timeout. Accepted keys: position, modifiers array, trial, force, noWaitAfter, strict, timeout.
Source
Thrown at internal/js/modules/k6/browser/browser/locator_mapping.go:409
return nil, fmt.Errorf("parsing type options: %w", err)
}
return promise(vu, func() (any, error) {
return nil, lo.Type(text, copts) //nolint:wrapcheck
}), nil
},
"hover": func(opts sobek.Value) (*sobek.Promise, error) {
copts := common.NewFrameHoverOptions(lo.Timeout())
if err := copts.Parse(vu.Context(), opts); err != nil {
return nil, fmt.Errorf("parsing hover options: %w", err)
}
return promise(vu, func() (any, error) {
return nil, lo.Hover(copts) //nolint:wrapcheck
}), nil
},
"tap": func(opts sobek.Value) (*sobek.Promise, error) {
copts := common.NewFrameTapOptions(lo.DefaultTimeout())
if err := copts.Parse(vu.Context(), opts); err != nil {
return nil, fmt.Errorf("parsing locator tap options: %w", err)
}
return promise(vu, func() (any, error) {
return nil, lo.Tap(copts) //nolint:wrapcheck
}), nil
},
"dispatchEvent": func(typ string, eventInit, opts sobek.Value) (*sobek.Promise, error) {
popts := common.NewFrameDispatchEventOptions(lo.DefaultTimeout())
if err := popts.Parse(vu.Context(), opts); err != nil {
return nil, fmt.Errorf("parsing locator dispatch event options: %w", err)
}
return promise(vu, func() (any, error) {
return nil, lo.DispatchEvent(typ, exportArg(eventInit), popts) //nolint:wrapcheck
}), nil
},
"waitFor": func(opts sobek.Value) (*sobek.Promise, error) {
copts := common.NewFrameWaitForSelectorOptions(lo.Timeout())
if err := copts.Parse(vu.Context(), opts); err != nil {
return nil, fmt.Errorf("parsing wait for options: %w", err)View on GitHub (pinned to 93accf6570)
Solutions
- Wrap modifiers in an array: tap({ modifiers: ['Shift', 'Meta'] }) or omit them
- Pass position as numeric {x, y} object only
- Coerce any string coordinates to Number before the call
- Remember tap uses the default action timeout, so pass timeout explicitly if needed
Example fix
// before
await page.locator('#btn').tap({ modifiers: 'Shift' });
// after
await page.locator('#btn').tap({ modifiers: ['Shift'] }); Defensive patterns
Strategy: validation
Validate before calling
function assertTapOpts(opts) {
if (opts === null || opts === undefined) return;
if (typeof opts !== 'object' || Array.isArray(opts)) {
throw new TypeError('tap options must be a plain object');
}
if ('modifiers' in opts && opts.modifiers !== undefined) {
if (!Array.isArray(opts.modifiers) || !opts.modifiers.every((m) => typeof m === 'string')) {
throw new TypeError('tap modifiers must be an array of strings, e.g. ["Shift"]');
}
}
if ('position' in opts && opts.position !== undefined) {
const p = opts.position;
if (typeof p !== 'object' || p === null || typeof p.x !== 'number' || typeof p.y !== 'number') {
throw new TypeError('tap position must be { x: number, y: number }');
}
}
} Type guard
function isTapOptions(v) {
if (v === null || v === undefined) return true;
if (typeof v !== 'object' || Array.isArray(v)) return false;
const modsOk = v.modifiers === undefined ||
(Array.isArray(v.modifiers) && v.modifiers.every((m) => typeof m === 'string'));
const posOk = v.position === undefined ||
(typeof v.position === 'object' && v.position !== null &&
typeof v.position.x === 'number' && typeof v.position.y === 'number');
return modsOk && posOk;
} Try / catch
try {
await locator.tap(opts);
} catch (e) {
if (/parsing locator tap options/.test(String(e.message))) {
throw new Error(`Bad tap options (modifiers must be string[], position must be {x,y} numbers): ${e.message}`);
}
throw e;
} Prevention
- Always wrap modifiers in an array: ['Shift'], never 'Shift'
- Express tap positions as numeric { x, y }
- Remember tap uses the default action timeout; set timeout explicitly when needed
When it happens
Trigger: tap({ modifiers: 'Shift' }) — string instead of ['Shift']; tap({ position: 'center' }) or { x: '10' }; tap({ modifiers: [1, 2] }) — non-string modifier entries.
Common situations: Mobile emulation scripts ported from Playwright where modifiers syntax differs; passing a single modifier string out of convenience; string coordinates from external data.
Related errors
- parsing get attribute options: %w
- parsing inner HTML options: %w
- parsing inner text options: %w
- parsing text content options: %w
- parsing input value options: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/c341ce3754dcb788.
Report an issue: GitHub.