grafana/k6 · error

parsing frame wait for navigation options

Error message

parsing frame wait for navigation options: %w

What it means

Thrown by page.waitForNavigation(opts) (and the frame variant) when FrameWaitForNavigationOptions.Parse rejects the options object. The parser validates keys like 'timeout', 'waitUntil' and 'url'; unknown keys or invalid values (bad waitUntil string, non-numeric timeout) are wrapped in this message.

Solutions

  1. Use { timeout: <ms>, waitUntil: 'load' | 'domcontentloaded' | 'networkidle', url: <string|RegExp> } only.
  2. Replace Puppeteer waitUntil values: 'networkidle0'/'networkidle2' → 'networkidle'.
  3. Trigger the navigation and the wait together (click then waitForNavigation in a Promise.all) so options stay minimal.
  4. Prefer page.waitForURL(url, opts) for URL-targeted waits.

Example fix

// before
await Promise.all([ page.waitForNavigation({ waitUntil: 'networkidle2' }), page.click('a.next') ]);

// after
await Promise.all([ page.waitForNavigation({ waitUntil: 'networkidle' }), page.click('a.next') ]);
Defensive patterns

Strategy: validation

Validate before calling

const opts = { timeout: 10000, waitUntil: 'load' };
if (!['load','domcontentloaded','networkidle'].includes(opts.waitUntil)) throw new Error(`invalid waitUntil '${opts.waitUntil}'`);
if (opts.url !== undefined && typeof opts.url !== 'string' && !(opts.url instanceof RegExp)) throw new Error('url must be string or RegExp');
await Promise.all([ page.waitForNavigation(opts), page.click('a') ]);

Type guard

const isNavOpts = (o) => o == null || (typeof o === 'object' && Object.keys(o).every(k => ['timeout','waitUntil','url'].includes(k)) && [undefined,'load','domcontentloaded','networkidle'].includes(o.waitUntil));

Try / catch

try { await page.waitForNavigation(opts); } catch (e) { if (e.message.includes('parsing frame wait for navigation options')) { /* normalize waitUntil and retry */ } throw e; }

Prevention

When it happens

Trigger: page.waitForNavigation({ waitUntil: 'networkidle2' }) (Puppeteer value); passing unknown keys; { url: 123 } where a string/regex is expected; string durations like { timeout: '10s' }.

Common situations: Migrating Puppeteer scripts (networkidle0/networkidle2 values); assuming Playwright's extra navigation options exist; racing navigation patterns where users add ad-hoc keys.

Related errors


AI-assisted analysis of grafana/k6@01ffac6f24 (2026-08-18). Data as JSON: /api/errors/6a0073a9e9e1fd21. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/browser/page_mapping.go:992

	}

	purl := parseStringOrRegex(url, false)
	tq, ctx, stop := newTaskQueue(vu)

	return promise(vu, func() (result any, reason error) {
		defer stop()
		return nil, target.WaitForURL(purl, popts, newRegExMatcher(ctx, vu, tq))
	}), nil
}

func mapWaitForNavigation(vu moduleVU, target interface {
	Timeout() time.Duration
	WaitForNavigation(*common.FrameWaitForNavigationOptions, common.RegExMatcher) (*common.Response, error)
}, opts sobek.Value,
) (*sobek.Promise, error) {
	popts := common.NewFrameWaitForNavigationOptions(target.Timeout())
	if err := popts.Parse(vu.Context(), opts); err != nil {
		return nil, fmt.Errorf("parsing frame wait for navigation options: %w", err)
	}

	// Only use task queue and RegExMatcher if a URL is specified.
	rm, stop := func() (common.RegExMatcher, func()) {
		if popts.URL == "" {
			return nil, func() {}
		}
		tq, ctx, stop := newTaskQueue(vu)
		return newRegExMatcher(ctx, vu, tq), stop
	}()

	return promise(vu, func() (any, error) {
		defer stop()

		resp, err := target.WaitForNavigation(popts, rm)
		if err != nil {
			return nil, err //nolint:wrapcheck
		}

View on GitHub (pinned to 01ffac6f24)