grafana/k6 · error

waiting for navigation: %w

Error message

waiting for navigation: %w

What it means

After a pointer action executes, k6 installs a navigation Barrier around it (unless NoWaitAfter) and waits for any navigation the action triggers. This error means Barrier.Wait failed: the navigation initiated by the click/tap did not complete within the remaining timeout, or the api context was cancelled (iteration ending, page closing).

Source

Thrown at internal/js/modules/k6/browser/common/element_handle.go:1780

				return nil, fmt.Errorf("checking hit target: %w", err)
			}
		}
		// Are we only "trialing" the action but not actually performing
		// it (ie. running the actionability checks).
		if opts.Trial {
			return nil, nil //nolint:nilnil
		}

		b := NewBarrier()
		h.frame.manager.addBarrier(b)
		defer h.frame.manager.removeBarrier(b)
		if res, err = fn(apiCtx, h, p); err != nil {
			return nil, fmt.Errorf("evaluating pointer action: %w", err)
		}
		// Do we need to wait for navigation to happen
		if !opts.NoWaitAfter {
			if err = b.Wait(apiCtx); err != nil {
				return nil, fmt.Errorf("waiting for navigation: %w", err)
			}
		}

		return res, nil
	}

	return func(apiCtx context.Context, resultCh chan any, errCh chan error) {
		if res, err := retryPointerAction(apiCtx, pointerFn, opts); err != nil {
			select {
			case <-apiCtx.Done():
			case errCh <- err:
			}
		} else {
			select {
			case <-apiCtx.Done():
			case resultCh <- res:
			}
		}

View on GitHub (pinned to 93accf6570)

Solutions

  1. If the action is not supposed to navigate, skip the wait: el.click({ noWaitAfter: true })
  2. If navigation is expected but slow, raise the action timeout: el.click({ timeout: '60s' })
  3. Ensure the target endpoint responds (fix/stub the backend or the load it is under)
  4. For downloads, use noWaitAfter and assert the download event instead of a navigation

Example fix

// before
page.$('#export').click(); // triggers download, navigation wait times out

// after
page.$('#export').click({ noWaitAfter: true });
Defensive patterns

Strategy: fallback

Validate before calling

// decide up front whether the action should navigate
const shouldNavigate = true; // set false for downloads/non-navigating buttons
if (!shouldNavigate) {
  el.click({ noWaitAfter: true });
} else {
  el.click({ timeout: '60s' });
}

Try / catch

try {
  el.click();
} catch (e) {
  if (String(e).includes('waiting for navigation')) {
    el.click({ noWaitAfter: true }); // navigation not required: skip barrier
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Click triggers a navigation whose response hangs (slow or stalled backend) so navigation never finishes before timeout; click starts a download rather than a navigation; context cancelled because the VU iteration ended or the page closed while waiting; NoWaitAfter left false (default) on actions not meant to navigate.

Common situations: Logout or submit buttons hitting dead endpoints in test environments; slow third-party redirects chains; clicks that trigger file downloads; strict iteration budgets cancelling the wait.

Related errors


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