{"record":{"id":"fa7062b1d024aa8f","repo":"grafana/k6","slug":"parsing-hover-options-w","errorCode":null,"errorMessage":"parsing hover options: %w","messagePattern":"parsing hover options: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/browser/frame_mapping.go","lineNumber":221,"sourceCode":"\t\t\t\tf.Referrer(),\n\t\t\t\tf.NavigationTimeout(),\n\t\t\t)\n\t\t\tif err := gopts.Parse(vu.Context(), opts); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing frame navigation options to %q: %w\", url, err)\n\t\t\t}\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\tresp, err := f.Goto(url, gopts)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err //nolint:wrapcheck\n\t\t\t\t}\n\n\t\t\t\treturn mapResponse(vu, resp), nil\n\t\t\t}), nil\n\t\t},\n\t\t\"hover\": func(selector string, opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tpopts := common.NewFrameHoverOptions(f.Timeout())\n\t\t\tif err := popts.Parse(vu.Context(), opts); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing hover options: %w\", err)\n\t\t\t}\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn nil, f.Hover(selector, popts) //nolint:wrapcheck\n\t\t\t}), nil\n\t\t},\n\t\t\"innerHTML\": func(selector string, opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tpopts := common.NewFrameInnerHTMLOptions(f.Timeout())\n\t\t\tif err := popts.Parse(vu.Context(), opts); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing inner HTML options: %w\", err)\n\t\t\t}\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn f.InnerHTML(selector, popts) //nolint:wrapcheck\n\t\t\t}), nil\n\t\t},\n\t\t\"innerText\": func(selector string, opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tpopts := common.NewFrameInnerTextOptions(f.Timeout())\n\t\t\tif err := popts.Parse(vu.Context(), opts); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing inner text options: %w\", err)","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/browser/frame_mapping.go#L203-L239","documentation":"The options object passed to frame.hover(selector, opts) failed to parse (frame_mapping.go:221). ElementHandleHoverOptions parses 'position' (must be {x: number, y: number}) and 'modifiers' (must be an array of strings); a value that cannot export to those types throws this error synchronously.","triggerScenarios":"frame.hover('#el', { position: 'center' }), { position: [10, 10] }, or { modifiers: 'Shift' } (string not array) - the sobek ExportTo fails and gets wrapped as 'parsing hover options:'.","commonSituations":"Reusing click/dblclick option objects verbatim for hover; JSON-sourced configs where numbers arrive as strings; Playwright ports using tuple positions or CSS-style position keywords.","solutions":["Use { position: { x: 10, y: 20 } } and { modifiers: ['Shift'] }","Coerce JSON-sourced values before calling: position: { x: Number(p.x), y: Number(p.y) }","Drop position entirely to hover the element center (the default)"],"exampleFix":"// before\nframe.hover('#menu', { position: 'center' });\n// after\nframe.hover('#menu', { position: { x: 150, y: 30 } });","handlingStrategy":"type-guard","validationCode":"const norm = {\n  ...opts,\n  ...(opts?.modifiers && !Array.isArray(opts.modifiers) ? { modifiers: String(opts.modifiers).split(',') } : {}),\n  ...(opts?.position ? { position: { x: Number(opts.position.x), y: Number(opts.position.y) } } : {}),\n};","typeGuard":"function isHoverOptions(o) {\n  if (o == null) return true;\n  const posOk = o.position == null || (typeof o.position === 'object' && !Array.isArray(o.position)\n    && Number.isFinite(Number(o.position.x)) && Number.isFinite(Number(o.position.y)));\n  const modOk = o.modifiers == null || (Array.isArray(o.modifiers) && o.modifiers.every(m => typeof m === 'string'));\n  return posOk && modOk;\n}","tryCatchPattern":"try {\n  await frame.hover(sel, norm);\n} catch (e) {\n  if (String(e.message).includes('parsing hover options')) throw new Error(`bad hover opts for ${sel}: ${JSON.stringify(opts)}`);\n  throw e;\n}","preventionTips":["Omit position to hover the element center; specify {x, y} numbers only","modifiers must be an array like ['Shift']","Validate option objects once where they enter the script (config load), not per call"],"tags":["k6","browser","frame","options-parsing","hover"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}