grafana/k6 · error

navigating to history entry

Error message

navigating %s to history entry %d: %w

What it means

This error is returned by Page.GoBack/GoForward (page.go history navigation) when the CDP call Page.navigate_to_history_entry fails while moving the page to a target index in the session history. The '%s' is the target URL taken from the history entries list and '%d' the history entry ID; failure usually means the browser target was closed, the navigation was interrupted, or the underlying CDP session dropped. A separate timeout wrapper converts deadline overruns into a k6ext.UserFriendlyError, so this specific wrap is for non-timeout protocol failures.

Solutions

  1. Verify the browser tab/target is still open before calling goBack/goForward
  2. Retry the navigation after waiting for the page to reach a stable lifecycle state
  3. Increase the navigation timeout option if the failure is caused by an overruns of the per-call deadline
  4. Check that no other code (e.g. page.close()) races with the history navigation
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at internal/js/modules/k6/browser/common/page.go:1659 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-08-18). Data as JSON: /api/errors/5b7dd38c3d2dfdd7. Report an issue: GitHub.

Appendix: source

Thrown at internal/js/modules/k6/browser/common/page.go:1664

	targetURL := entries[targetIndex].URL

	timeoutCtx, timeoutCancelFn := context.WithTimeout(p.ctx, opts.Timeout)
	defer timeoutCancelFn()

	navAction := page.NavigateToHistoryEntry(historyEntryID)
	if err := navAction.Do(cdp.WithExecutor(p.ctx, p.session)); err != nil {
		return nil, fmt.Errorf("navigating to history entry %d: %w", historyEntryID, err)
	}

	wrapTimeoutError := func(err error) error {
		if errors.Is(err, context.DeadlineExceeded) {
			err = &k6ext.UserFriendlyError{
				Err:     err,
				Timeout: opts.Timeout,
			}
		}
		p.logger.Debugf("Page:GoBackForward", "timeoutCtx done: %v", err)
		return fmt.Errorf("navigating %s to history entry %d: %w", direction, historyEntryID, err)
	}

	// Poll for URL change, don't rely on lifecycle events since bfcache
	// restorations don't re-fire them.
	ticker := time.NewTicker(50 * time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case <-p.ctx.Done():
			return nil, ContextErr(p.ctx)
		case <-timeoutCtx.Done():
			return nil, wrapTimeoutError(ContextErr(timeoutCtx))
		case <-ticker.C:
			mainFrame := p.frameManager.MainFrame()
			if mainFrame == nil {
				continue
			}

View on GitHub (pinned to 3fcf5388d7)