{"record":{"id":"7e261bfcce9583d5","repo":"grafana/k6","slug":"parsing-is-in-viewport-options-w","errorCode":null,"errorMessage":"parsing is in viewport options: %w","messagePattern":"parsing is in viewport options: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/browser/locator_mapping.go","lineNumber":176,"sourceCode":"\t\t\t\treturn nil, fmt.Errorf(\"parsing is enabled options: %w\", err)\n\t\t\t}\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn lo.IsEnabled(copts) //nolint:wrapcheck\n\t\t\t}), nil\n\t\t},\n\t\t\"isDisabled\": func(opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tcopts, err := parseFrameIsDisabledOptions(rt, opts, lo.Timeout())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing is disabled options: %w\", err)\n\t\t\t}\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn lo.IsDisabled(copts) //nolint:wrapcheck\n\t\t\t}), nil\n\t\t},\n\t\t\"isInViewport\": func(opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tcopts, err := parseFrameIsInViewportOptions(rt, opts, lo.Timeout())\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing is in viewport options: %w\", err)\n\t\t\t}\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn lo.IsInViewport(copts) //nolint:wrapcheck\n\t\t\t}), nil\n\t\t},\n\t\t\"isVisible\": func() *sobek.Promise {\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn lo.IsVisible() //nolint:wrapcheck\n\t\t\t})\n\t\t},\n\t\t\"isHidden\": func() *sobek.Promise {\n\t\t\treturn promise(vu, func() (any, error) {\n\t\t\t\treturn lo.IsHidden() //nolint:wrapcheck\n\t\t\t})\n\t\t},\n\t\t\"fill\": func(value string, opts sobek.Value) (*sobek.Promise, error) {\n\t\t\tcopts, err := parseFrameFillOptions(rt, opts, lo.Timeout())\n\t\t\tif err != nil {","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/grafana/k6/blob/8d06114777191d21ef885d05c5f8aa9e1ed838ae/internal/js/modules/k6/browser/browser/locator_mapping.go#L158-L194","documentation":"Thrown synchronously when the options argument to locator.isInViewport() fails to parse. The mapping (locator_mapping.go:173-177) creates common.FrameIsInViewportOptions and wraps Parse failures as \"parsing is in viewport options: %w\". Parse (frame_options.go:449-462) runs FrameBaseOptions.Parse for strict/timeout and then reads an optional \"ratio\" via ToFloat; the coercing accessors do not fail on ordinary wrong types, so the wrapped error comes from sobek raising during property access (throwing getter, Proxy trap, or throwing toPrimitive during the ratio/timeout coercion).","triggerScenarios":"opts.ratio implemented as a getter that throws; a Proxy around options with raising get/ownKeys traps; a ratio or timeout value whose valueOf/Symbol.toPrimitive raises during ToFloat/ToInteger.","commonSituations":"Passing a ratio computed from a helper that throws on division by zero inside a getter; tracing Proxies; k6 scripts migrated from Playwright where isInViewport returns a ratio and callers pass computed thresholds as accessors.","solutions":["Pass a plain literal: locator.isInViewport({ ratio: 0.5, timeout: 3000 })","Compute ratio beforehand and guard divide-by-zero before the call","Keep options free of Proxies and accessor properties","try/catch the call for a controlled failure message"],"exampleFix":"// before\nconst opts = { get ratio() { return visible / total; } }; // throws when total === 0\nawait locator.isInViewport(opts);\n\n// after\nif (total === 0) throw new Error('cannot compute viewport ratio');\nawait locator.isInViewport({ ratio: visible / total });","handlingStrategy":"validation","validationCode":"function assertViewportOptions(opts) {\n  if (opts == null) return;\n  if (typeof opts !== 'object') throw new TypeError('isInViewport options must be an object');\n  if (opts.ratio !== undefined && !Number.isFinite(opts.ratio))\n    throw new TypeError(`ratio must be a number, got ${typeof opts.ratio}`);\n  if (opts.timeout !== undefined && !Number.isFinite(opts.timeout))\n    throw new TypeError(`timeout must be a number, got ${typeof opts.timeout}`);\n}\nassertViewportOptions(opts);\nconst ratio = await locator.isInViewport(opts);","typeGuard":"function isViewportOptions(o) {\n  return o == null || (typeof o === 'object' &&\n    (o.ratio === undefined || Number.isFinite(o.ratio)) &&\n    (o.timeout === undefined || Number.isFinite(o.timeout)));\n}","tryCatchPattern":"try { await locator.isInViewport(opts); } catch (e) { if (String(e).includes('parsing is in viewport options')) throw new Error(`bad isInViewport options: ${JSON.stringify(opts)}`); throw e; }","preventionTips":["Compute ratio before the call and guard divide-by-zero","Pass ratio as a plain number between 0 and 1","Avoid getters that throw on option objects"],"tags":["k6","browser","locator","isinviewport","options","ratio"],"backgroundTag":"invalid-options-object","analyzedSha":"8d06114777191d21ef885d05c5f8aa9e1ed838ae","analyzedAt":"2026-09-14T20:10:14.619Z","contentChangedAt":"2026-09-14T20:10:14.619Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}