grafana/k6 · error

parsing text content options: %w

Error message

parsing text content options: %w

What it means

Thrown when locator.textContent(opts) fails to parse options into FrameTextContentOptions (embeds FrameBaseOptions: strict boolean, timeout number in ms). The mapping wraps the failure as 'parsing text content options: %w'. On success the promise resolves to the text, or null when the node has no text content; this error happens before any browser round-trip, purely from an unparseable opts argument.

Source

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

			if err := copts.Parse(vu.Context(), opts); 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)
		},
		"nth": func(nth int) *sobek.Object {
			ml := mapLocator(vu, lo.Nth(nth))
			return rt.ToValue(ml).ToObject(rt)
		},
		"textContent": func(opts sobek.Value) (*sobek.Promise, error) {
			copts := common.NewFrameTextContentOptions(lo.Timeout())
			if err := copts.Parse(vu.Context(), opts); err != nil {
				return nil, fmt.Errorf("parsing text content options: %w", err)
			}
			return promise(vu, func() (any, error) {
				s, ok, err := lo.TextContent(copts)
				if err != nil {
					return nil, err //nolint:wrapcheck
				}
				if !ok {
					return nil, nil
				}
				return s, nil
			}), nil
		},
		"inputValue": func(opts sobek.Value) (*sobek.Promise, error) {
			copts := common.NewFrameInputValueOptions(lo.Timeout())
			if err := copts.Parse(vu.Context(), opts); err != nil {
				return nil, fmt.Errorf("parsing input value options: %w", err)
			}
			return promise(vu, func() (any, error) {

View on GitHub (pinned to 93accf6570)

Solutions

  1. Call textContent() with no options, or pass { timeout: <number-ms> } only
  2. Remove state/strict-unrelated keys copied from waitFor(selector, { state }) examples
  3. Ensure the argument is a plain object literal
  4. Prefer locator.setDefaultTimeout() for site-wide timeouts

Example fix

// before
const t = await page.locator('.msg').textContent({ state: 'visible', timeout: '5s' });

// after
const t = await page.locator('.msg').textContent({ timeout: 5000 });
Defensive patterns

Strategy: validation

Validate before calling

function assertBaseOpts(method, opts) {
  if (opts === null || opts === undefined) return;
  if (typeof opts !== 'object' || Array.isArray(opts)) {
    throw new TypeError(`${method} options must be a plain object, got ${typeof opts}`);
  }
  if ('timeout' in opts && typeof opts.timeout !== 'number') {
    throw new TypeError(`${method} timeout must be a number (ms)`);
  }
}
assertBaseOpts('textContent', opts);

Type guard

function isLocatorBaseOptions(v) {
  if (v === null || v === undefined) return true;
  if (typeof v !== 'object' || Array.isArray(v)) return false;
  return (v.timeout === undefined || typeof v.timeout === 'number') &&
         (v.strict === undefined || typeof v.strict === 'boolean');
}

Try / catch

try {
  const t = await locator.textContent(opts);
} catch (e) {
  if (/parsing text content options/.test(String(e.message))) {
    throw new Error(`Bad textContent options: ${JSON.stringify(opts)}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling locator.textContent('visible') or textContent(5000) — scalar in the opts slot; passing { state: 'visible' } (a waitFor option, not valid here) under strict parsing; non-object values such as arrays or functions.

Common situations: Confusing textContent options with waitFor options when adapting examples; reusing an options object built for a different locator method; passing millisecond numbers positionally out of habit from older APIs.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/efc685eac0eb3de1. Report an issue: GitHub.