grafana/k6 · error

parsing wait for options: %w

Error message

parsing wait for options: %w

What it means

Thrown when locator.waitFor(opts) fails to parse options into FrameWaitForSelectorOptions. This is a live, strict error path for the state key: only 'attached', 'detached', 'visible', 'hidden' are accepted, and anything else returns '<state> is not a valid DOM state', wrapped as 'parsing wait for options: ...'. Also accepted: strict boolean and timeout number in ms (coerced leniently).

Source

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

				return nil, fmt.Errorf("parsing locator tap options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return nil, lo.Tap(copts) //nolint:wrapcheck
			}), nil
		},
		"dispatchEvent": func(typ string, eventInit, opts sobek.Value) (*sobek.Promise, error) {
			popts := common.NewFrameDispatchEventOptions(lo.DefaultTimeout())
			if err := popts.Parse(vu.Context(), opts); err != nil {
				return nil, fmt.Errorf("parsing locator dispatch event options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return nil, lo.DispatchEvent(typ, exportArg(eventInit), popts) //nolint:wrapcheck
			}), nil
		},
		"waitFor": func(opts sobek.Value) (*sobek.Promise, error) {
			copts := common.NewFrameWaitForSelectorOptions(lo.Timeout())
			if err := copts.Parse(vu.Context(), opts); err != nil {
				return nil, fmt.Errorf("parsing wait for options: %w", err)
			}
			return promise(vu, func() (any, error) {
				return nil, lo.WaitFor(copts) //nolint:wrapcheck
			}), nil
		},
	}
}

func parseLocatorOptions(rt *sobek.Runtime, opts sobek.Value) *common.LocatorOptions {
	if k6common.IsNullish(opts) {
		return nil
	}

	var popts common.LocatorOptions

	obj := opts.ToObject(rt)
	for _, k := range obj.Keys() {
		switch k {

View on GitHub (pinned to 93accf6570)

Solutions

  1. Use one of the four valid states: waitFor({ state: 'visible' }) — attached, detached, visible, hidden
  2. Lowercase the state string exactly
  3. Pass the selector to locator(), not to waitFor — the opts slot accepts only state/strict/timeout
  4. Set timeout numerically in ms alongside the state

Example fix

// before
await page.locator('.toast').waitFor({ state: 'Shown' });

// after
await page.locator('.toast').waitFor({ state: 'visible', timeout: 5000 });
Defensive patterns

Strategy: validation

Validate before calling

const WAIT_FOR_STATES = new Set(['attached', 'detached', 'visible', 'hidden']);
function assertWaitForOpts(opts) {
  if (opts === null || opts === undefined) return;
  if (typeof opts !== 'object' || Array.isArray(opts)) {
    throw new TypeError('waitFor options must be a plain object');
  }
  if ('state' in opts && !WAIT_FOR_STATES.has(opts.state)) {
    throw new TypeError(`waitFor state must be one of ${[...WAIT_FOR_STATES].join(', ')}, got ${JSON.stringify(opts.state)}`);
  }
  if ('timeout' in opts && typeof opts.timeout !== 'number') {
    throw new TypeError('waitFor timeout must be a number (ms)');
  }
}

Type guard

function isWaitForOptions(v) {
  if (v === null || v === undefined) return true;
  if (typeof v !== 'object' || Array.isArray(v)) return false;
  const stateOk = v.state === undefined ||
    ['attached', 'detached', 'visible', 'hidden'].includes(v.state);
  return stateOk && (v.timeout === undefined || typeof v.timeout === 'number');
}

Try / catch

try {
  await locator.waitFor(opts);
} catch (e) {
  if (/is not a valid DOM state/.test(String(e.message))) {
    throw new Error(`waitFor state must be attached|detached|visible|hidden: ${e.message}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: waitFor({ state: 'shown' }) or { state: 'displayed' } — not valid state names; case errors like { state: 'Visible' }; passing a selector string into the opts slot: waitFor('#id').

Common situations: Translating wait conditions from other frameworks (Selenium's visibility wording, Cypress should('be.visible')); typos and case mismatches; expecting k6 to accept Playwright's full waitForSelector option set (e.g. polling keys are not read here).

Related errors


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