grafana/k6 · error

parsing waitForNavigation options: %w

Error message

parsing waitForNavigation options: %w

What it means

This error comes from the `waitUntil` branch of FrameWaitForNavigationOptions.Parse (frame_options.go:730). waitForNavigation validates its waitUntil via LifecycleEvent.UnmarshalText, which accepts only "load", "domcontentloaded" and "networkidle". Any other string aborts option parsing with this wrapped error before the navigation wait begins.

Source

Thrown at internal/js/modules/k6/browser/common/frame_options.go:730

		opts := opts.ToObject(rt)
		for _, k := range opts.Keys() {
			switch k {
			case "url":
				var val string
				switch opts.Get(k).ExportType() {
				case reflect.TypeFor[string]():
					val = fmt.Sprintf("'%s'", opts.Get(k).String()) // Strings require quotes
				default: // JS Regex, CSS, numbers or booleans
					val = opts.Get(k).String() // No quotes
				}

				o.URL = val
			case "timeout":
				o.Timeout = time.Duration(opts.Get(k).ToInteger()) * time.Millisecond
			case "waitUntil":
				lifeCycle := opts.Get(k).String()
				if err := o.WaitUntil.UnmarshalText([]byte(lifeCycle)); err != nil {
					return fmt.Errorf("parsing waitForNavigation options: %w", err)
				}
			}
		}
	}
	return nil
}

func NewFrameWaitForSelectorOptions(defaultTimeout time.Duration) *FrameWaitForSelectorOptions {
	return &FrameWaitForSelectorOptions{
		State:   DOMElementStateVisible,
		Strict:  false,
		Timeout: defaultTimeout,
	}
}

// Parse parses the frame waitForSelector options.
func (o *FrameWaitForSelectorOptions) Parse(ctx context.Context, opts sobek.Value) error {
	rt := k6ext.Runtime(ctx)

View on GitHub (pinned to 93accf6570)

Solutions

  1. Set waitUntil to "load", "domcontentloaded" or "networkidle" exactly
  2. Keep timeout (milliseconds) and waitUntil keys separate; do not nest or rename them
  3. If wrapping gotos in waitForNavigation, use the same lifecycle value on both calls for consistent behavior

Example fix

// before
frame.waitForNavigation({ waitUntil: 'networkIdle', timeout: 5000 });

// after
frame.waitForNavigation({ waitUntil: 'networkidle', timeout: 5000 });
Defensive patterns

Strategy: validation

Validate before calling

const WAIT_UNTIL = ['load', 'domcontentloaded', 'networkidle'];
if (opts && opts.waitUntil !== undefined && !WAIT_UNTIL.includes(opts.waitUntil)) {
  throw new Error(`invalid waitUntil: ${opts.waitUntil}`);
}
frame.waitForNavigation(opts);

Type guard

function isWaitUntil(v: unknown): v is 'load' | 'domcontentloaded' | 'networkidle' {
  return v === 'load' || v === 'domcontentloaded' || v === 'networkidle';
}

Prevention

When it happens

Trigger: frame.waitForNavigation({ waitUntil: 'load-complete' }) or page.waitForNavigation({ waitUntil: 'networkIdle' }); also passing a URL string as waitUntil by mixing up option keys. Note the same parser also builds o.URL from a `url` key and parses `timeout` in milliseconds.

Common situations: Scripts adapted from Playwright waitForURL/waitForNavigation examples that use different lifecycle names, or camelCase spellings like 'networkIdle' which k6 does not accept.

Related errors


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