grafana/k6 · error

parsing inner HTML options

Error message

parsing inner HTML options: %w

What it means

Thrown synchronously when the options argument to locator.innerHTML() fails to parse. The mapping (locator_mapping.go:305-309) creates common.FrameInnerHTMLOptions (FrameBaseOptions seeded with the locator timeout) and wraps Parse failures as "parsing inner HTML options: %w". FrameBaseOptions.Parse reads only strict and timeout via coercing accessors and returns nil for ordinary values, so the wrapped error indicates sobek raised while accessing properties of the options object — a throwing getter, Proxy trap, or throwing coercion.

Solutions

  1. Call locator.innerHTML() with no options or a plain { timeout: ms } literal
  2. Compute values first; keep options as plain data
  3. Unwrap Proxies before passing to browser APIs
  4. try/catch around the call for controlled failure reporting

Example fix

// before
await locator.innerHTML({ get timeout() { return this.t; } }); // undefined this in getter throws

// after
await locator.innerHTML({ timeout: 3000 });
Defensive patterns

Strategy: try-catch

Type guard

function isPlainBaseOptions(o) {
  return o == null || (typeof o === 'object' &&
    (o.timeout === undefined || typeof o.timeout === 'number') &&
    (o.strict === undefined || typeof o.strict === 'boolean'));
}

Try / catch

try {
  const html = await locator.innerHTML(opts);
} catch (e) {
  throw new Error(`innerHTML failed (options must be plain { timeout, strict }): ${e}`);
}

Prevention

When it happens

Trigger: A throwing getter on timeout/strict; Proxy-wrapped options with raising get/ownKeys traps; a timeout whose implicit conversion to number throws.

Common situations: Snapshot helpers that lazily compute timeouts in getters; Proxied arguments from tracing tools; class-based options objects with accessors.

Related errors


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

Appendix: source

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

			if k6common.IsNullish(title) {
				return nil, errors.New("missing required argument 'title'")
			}
			ptitle, popts := parseGetByBaseOptions(vu.Context(), title, false, opts)

			ml := mapLocator(vu, lo.GetByTitle(ptitle, popts))
			return rt.ToValue(ml).ToObject(rt), nil
		},
		"locator": func(selector string, opts sobek.Value) mapping {
			return mapLocator(vu, lo.Locator(selector, parseLocatorOptions(rt, opts)))
		},
		"frameLocator": func(selector string) *sobek.Object {
			mfl := mapFrameLocator(vu, lo.FrameLocator(selector))
			return rt.ToValue(mfl).ToObject(rt)
		},
		"innerHTML": func(opts sobek.Value) (*sobek.Promise, error) {
			copts, err := parseFrameInnerHTMLOptions(rt, opts, lo.Timeout())
			if err != nil {
				return nil, fmt.Errorf("parsing inner HTML options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return lo.InnerHTML(copts) //nolint:wrapcheck
			}), nil
		},
		"innerText": func(opts sobek.Value) (*sobek.Promise, error) {
			copts, err := parseFrameInnerTextOptions(rt, opts, lo.Timeout())
			if err != nil {
				return nil, fmt.Errorf("parsing inner text options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return lo.InnerText(copts) //nolint:wrapcheck
			}), nil
		},
		"last": func() *sobek.Object {
			ml := mapLocator(vu, lo.Last())
			return rt.ToValue(ml).ToObject(rt)
		},

View on GitHub (pinned to 8d06114777)