grafana/k6 · error
page.route(' '): iteration ended before route completed
Error message
page.route('%s'): iteration ended before route completed What it means
Returned from the route callback registered by page.route(pattern, handler) when the k6 iteration (VU) context is canceled while the handler task is still queued or executing. queueTask returns context.Canceled, which is translated into this explicit message: the script iteration ended before the route handler completed.
Solutions
- Ensure every route handler synchronously settles the route (continue/fulfill/abort) without long awaits.
- Call page.unroute(pattern) when done so no handler remains registered across iteration teardown.
- Lengthen iteration/scene duration if the intercepted request legitimately needs more time.
- Intercept fewer requests with a tighter pattern so handlers are not invoked near iteration end.
Example fix
// before
await page.route('**/api/**', route => route.fulfill({ body: slowBody() })); // slow await may outlive iteration
// after
const body = slowBody();
await page.route('**/api/**', route => route.fulfill({ body }));
// ... at end of iteration:
await page.unroute('**/api/**'); Defensive patterns
Strategy: try-catch
Try / catch
try {
await page.route('**/api/**', handler);
} catch (e) {
if (e.message.includes('iteration ended before route completed')) {
// benign at teardown: iteration duration expired before the intercepted request arrived
console.warn('route outlived iteration; consider unroute() earlier');
}
} Prevention
- Always pair page.route() with page.unroute() at the end of the iteration.
- Settle every intercepted request synchronously (continue/fulfill/abort) without long awaits.
- Size iteration duration to comfortably cover the intercepted traffic.
When it happens
Trigger: Registering page.route() and letting the iteration finish without the route ever being hit (or mid-handler); a route handler that awaits something long (e.g. route.fulfill delayed) while the scenario's iteration duration expires; graceful/normal scenario teardown with routes still active.
Common situations: Short per-iteration scenarios (e.g. 1s each) where the routed request never completes; forgetting page.unroute() at the end; route handlers performing sleeps or slow fixture building; browser close racing an in-flight intercepted request.
Related errors
- page.route(' ')
- evaluate requires a page function
- evaluateHandle requires a page function
- executing page.on(' ') handler
- executing waitForEvent predicate
AI-assisted analysis of grafana/k6@8d06114777 (2026-08-18).
Data as JSON: /api/errors/175966064f4f68ce.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/browser/page_mapping.go:983
}
return a, o
}
// mapPageRoute maps the requested page.route event to the Sobek runtime.
func mapPageRoute(vu moduleVU, p *common.Page) func(sobek.Value, sobek.Callable) (*sobek.Promise, error) {
return func(path sobek.Value, cb sobek.Callable) (*sobek.Promise, error) {
ctx := vu.Context()
ppath := parseStringOrRegex(path, false)
tq := vu.get(ctx, p.TargetID())
route := func(r *common.Route) error {
_, err := queueTask(ctx, tq, func() (any, error) {
return cb(sobek.Undefined(), vu.Runtime().ToValue(mapRoute(vu, r)))
})()
if errors.Is(err, context.Canceled) {
return fmt.Errorf("page.route('%s'): iteration ended before route completed", path)
}
if err != nil {
return fmt.Errorf("page.route('%s'): %w", path, err)
}
return nil
}
return promise(vu, func() (any, error) {
return nil, p.Route(ppath, route, newRegExMatcher(ctx, vu, tq))
}), nil
}
}
func mapWaitForURL(rt *sobek.Runtime, vu moduleVU, target interface {
Timeout() time.Duration
WaitForURL(urlPattern string, opts *common.FrameWaitForURLOptions, rm common.RegExMatcher) error
}, url sobek.Value, opts sobek.Value,
) (*sobek.Promise, error) {View on GitHub (pinned to 8d06114777)