grafana/k6 · error

parsing is in viewport options

Error message

parsing is in viewport options: %w

What it means

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).

Solutions

  1. Pass a plain literal: locator.isInViewport({ ratio: 0.5, timeout: 3000 })
  2. Compute ratio beforehand and guard divide-by-zero before the call
  3. Keep options free of Proxies and accessor properties
  4. try/catch the call for a controlled failure message

Example fix

// before
const opts = { get ratio() { return visible / total; } }; // throws when total === 0
await locator.isInViewport(opts);

// after
if (total === 0) throw new Error('cannot compute viewport ratio');
await locator.isInViewport({ ratio: visible / total });
Defensive patterns

Strategy: validation

Validate before calling

function assertViewportOptions(opts) {
  if (opts == null) return;
  if (typeof opts !== 'object') throw new TypeError('isInViewport options must be an object');
  if (opts.ratio !== undefined && !Number.isFinite(opts.ratio))
    throw new TypeError(`ratio must be a number, got ${typeof opts.ratio}`);
  if (opts.timeout !== undefined && !Number.isFinite(opts.timeout))
    throw new TypeError(`timeout must be a number, got ${typeof opts.timeout}`);
}
assertViewportOptions(opts);
const ratio = await locator.isInViewport(opts);

Type guard

function isViewportOptions(o) {
  return o == null || (typeof o === 'object' &&
    (o.ratio === undefined || Number.isFinite(o.ratio)) &&
    (o.timeout === undefined || Number.isFinite(o.timeout)));
}

Try / catch

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; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

Thrown at internal/js/modules/k6/browser/browser/locator_mapping.go:176

				return nil, fmt.Errorf("parsing is enabled options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return lo.IsEnabled(copts) //nolint:wrapcheck
			}), nil
		},
		"isDisabled": func(opts sobek.Value) (*sobek.Promise, error) {
			copts, err := parseFrameIsDisabledOptions(rt, opts, lo.Timeout())
			if err != nil {
				return nil, fmt.Errorf("parsing is disabled options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return lo.IsDisabled(copts) //nolint:wrapcheck
			}), nil
		},
		"isInViewport": func(opts sobek.Value) (*sobek.Promise, error) {
			copts, err := parseFrameIsInViewportOptions(rt, opts, lo.Timeout())
			if err != nil {
				return nil, fmt.Errorf("parsing is in viewport options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return lo.IsInViewport(copts) //nolint:wrapcheck
			}), nil
		},
		"isVisible": func() *sobek.Promise {
			return promise(vu, func() (any, error) {
				return lo.IsVisible() //nolint:wrapcheck
			})
		},
		"isHidden": func() *sobek.Promise {
			return promise(vu, func() (any, error) {
				return lo.IsHidden() //nolint:wrapcheck
			})
		},
		"fill": func(value string, opts sobek.Value) (*sobek.Promise, error) {
			copts, err := parseFrameFillOptions(rt, opts, lo.Timeout())
			if err != nil {

View on GitHub (pinned to 8d06114777)