{"record":{"id":"1e0d3c24d9eebc2b","repo":"grafana/k6","slug":"parsing-new-frame-check-options-w","errorCode":null,"errorMessage":"parsing new frame check options: %w","messagePattern":"parsing new frame check options: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/browser/frame_mapping.go","lineNumber":22,"sourceCode":"\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/grafana/sobek\"\n\n\t\"go.k6.io/k6/v2/internal/js/modules/k6/browser/common\"\n\tk6common \"go.k6.io/k6/v2/js/common\"\n)\n\n// mapFrame to the JS module.\n//\n//nolint:funlen,gocognit,cyclop\nfunc mapFrame(vu moduleVU, f *common.Frame) mapping {\n\trt := vu.Runtime()\n\tmaps := mapping{\n\t\t\"check\": func(selector string, opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tpopts := common.NewFrameCheckOptions(f.Timeout())\n\t\t\tif err := popts.Parse(vu.Context(), opts); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing new frame check options: %w\", err)\n\t\t\t}\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn nil, f.Check(selector, popts) //nolint:wrapcheck\n\t\t\t}), nil\n\t\t},\n\t\t\"childFrames\": func() []mapping {\n\t\t\tcfs := f.ChildFrames()\n\t\t\tmcfs := make([]mapping, 0, len(cfs))\n\t\t\tfor _, fr := range cfs {\n\t\t\t\tmcfs = append(mcfs, mapFrame(vu, fr))\n\t\t\t}\n\t\t\treturn mcfs\n\t\t},\n\t\t\"click\": func(selector string, opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tpopts, err := parseFrameClickOptions(vu.Context(), opts, f.Timeout())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/browser/frame_mapping.go#L4-L40","documentation":"The options object passed to frame.check(selector, opts) failed to parse (frame_mapping.go:22). FrameCheckOptions ultimately parses pointer options; the only field that can currently fail is 'position', which must be a plain object with numeric x and y (element_handle_options.go:189-195 uses rt.ExportTo into map[string]float64).","triggerScenarios":"Calling frame.check('#cb', { position: 'center' }), { position: [10, 20] } (array, not object), or { position: { x: '10', y: 20 } } (string x) - sobek cannot export the value into map[string]float64 and the error is thrown synchronously before the promise is created.","commonSituations":"Porting Playwright scripts where position is sometimes given as a tuple or string; dynamic option objects built from JSON configs where numbers arrive as strings; spreads of default objects that accidentally include a malformed position.","solutions":["Pass position as an object of numbers: { position: { x: 10, y: 20 } } or omit it","If options come from JSON, coerce before the call: { ...opts, position: opts.position && { x: +opts.position.x, y: +opts.position.y } }","Wrap the call in try/catch - parse errors throw synchronously, not as promise rejections"],"exampleFix":"// before\nframe.check('#accept', { position: 'center' });\n// after\nframe.check('#accept', { position: { x: 120, y: 40 } });","handlingStrategy":"type-guard","validationCode":"// run before frame.check\nconst opts2 = opts && opts.position\n  ? { ...opts, position: { x: Number(opts.position.x), y: Number(opts.position.y) } }\n  : opts;","typeGuard":"function isValidPosition(p) {\n  return p == null ||\n    (typeof p === 'object' && !Array.isArray(p) &&\n      Number.isFinite(Number(p.x)) && Number.isFinite(Number(p.y)));\n}\nif (!isValidPosition(opts?.position)) throw new Error('position must be {x: number, y: number}');","tryCatchPattern":"try {\n  const p = frame.check(sel, opts); // parse errors throw synchronously here\n  await p;                          // runtime errors reject here\n} catch (e) {\n  console.error(`check failed for ${sel}: ${e.message}`);\n}","preventionTips":["Pass position as {x, y} numbers only - never a string, keyword, or array","Type-check option objects once when they come from JSON/config","Keep option builders centralized so malformed shapes fail one loud, early check"],"tags":["k6","browser","frame","options-parsing","javascript"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}