grafana/k6 · error

waiting for navigation: %w

Error message

waiting for navigation: %w

What it means

Same handler as the URL variant, but emitted when opts.URL is empty: Frame.WaitForNavigation was waiting for ANY navigation and the wait ended in error (usually timeout, wrapped in k6ext.UserFriendlyError with opts.Timeout) before a NavigationEvent arrived. Without a pattern there is nothing to match, so the message carries only the friendly timeout.

Source

Thrown at internal/js/modules/k6/browser/common/frame.go:2186

		return nil, nil //nolint:nilnil
	}

	return resp, nil
}

func (f *Frame) handleWaitForNavigationTimeoutErrorFn(opts *FrameWaitForNavigationOptions) func(err error) error {
	return func(err error) error {
		f.log.Debugf("Frame:WaitForNavigation",
			"fid:%v furl:%s timeoutCtx done: %v", f.ID(), f.URL(), err)
		if err != nil {
			e := &k6ext.UserFriendlyError{
				Err:     err,
				Timeout: opts.Timeout,
			}
			if opts.URL != "" {
				return fmt.Errorf("waiting for navigation to URL matching %q: %w", opts.URL, e)
			}
			return fmt.Errorf("waiting for navigation: %w", e)
		}

		return nil
	}
}

// WaitForSelector waits for the given selector to match the waiting criteria.
func (f *Frame) WaitForSelector(selector string, popts *FrameWaitForSelectorOptions) (*ElementHandle, error) {
	handle, err := f.waitForSelectorRetry(selector, popts, maxRetry)
	if err != nil {
		return nil, fmt.Errorf("waiting for selector %q: %w", selector, err)
	}

	return handle, nil
}

// WaitForTimeout waits the specified amount of milliseconds.
func (f *Frame) WaitForTimeout(timeout int64) {

View on GitHub (pinned to 93accf6570)

Solutions

  1. Register the wait before the action and await both: const nav = page.waitForNavigation(); await el.click(); await nav;
  2. If it is an SPA route change, use page.waitForURL instead — a history pushState may not emit a navigation event
  3. Increase the timeout option

Example fix

// before
await page.click('#next');
await page.waitForNavigation(); // registered too late, or SPA route change emits nothing

// after
const nav = page.waitForNavigation({ timeout: 60_000 });
await page.click('#next');
await nav;
Defensive patterns

Strategy: try-catch

Type guard

function isNavTimeoutNoURL(e) {
  return e instanceof Error && /waiting for navigation/.test(e.message);
}

Try / catch

try {
  const nav = page.waitForNavigation({ timeout: 60_000 });
  await el.click();
  await nav;
} catch (e) {
  if (isNavTimeoutNoURL(e)) { await page.waitForURL('**/next**'); } // SPA fallback
  else throw e;
}

Prevention

When it happens

Trigger: page.waitForNavigation() with no url option where the accompanying action never triggers a navigation; the navigation occurs but the frame is detached or the page closes first; timeout too short for the new document's lifecycle.

Common situations: Clicking a button that only changes route via SPA history (no document navigation event in some setups); calling waitForNavigation after the navigation already happened; page.close() during the wait.

Related errors


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