grafana/k6 · error
waitForEvent timed out after %v
Error message
waitForEvent timed out after %v
What it means
Thrown by BrowserContext.waitForEvent when no new page event satisfies the wait within the given timeout. The implementation selects on the context cancellation, a time.After(timeout) timer, the event channel, and the error channel; if the timer fires first you get 'waitForEvent timed out after <duration>'. Unlike the other branches, this is a plain timeout condition, not a wrapped lower-level failure.
Source
Thrown at internal/js/modules/k6/browser/common/browser_context.go:383
}
evCancelCtx, evCancelFn := context.WithCancel(b.ctx)
defer evCancelFn() // This will remove the event handler once we return from here.
chEvHandler := make(chan Event)
ch := make(chan any)
errCh := make(chan error)
go b.runWaitForEventHandler(evCancelCtx, chEvHandler, predicateFn, ch, errCh)
b.on(evCancelCtx, []string{EventBrowserContextPage}, chEvHandler)
select {
case <-b.ctx.Done():
return nil, ContextErr(b.ctx) //nolint:wrapcheck
case <-time.After(timeout):
b.logger.Debugf("BrowserContext:WaitForEvent:timeout", "bctxid:%v event:%q", b.id, event)
return nil, fmt.Errorf("waitForEvent timed out after %v", timeout)
case evData := <-ch:
b.logger.Debugf("BrowserContext:WaitForEvent:evData", "bctxid:%v event:%q", b.id, event)
return evData, nil
case err := <-errCh:
b.logger.Debugf("BrowserContext:WaitForEvent:err", "bctxid:%v event:%q, err:%v", b.id, event, err)
return nil, err
}
}
// runWaitForEventHandler can work with a nil predicateFn. If predicateFn is
// nil it will return the response straight away.
func (b *BrowserContext) runWaitForEventHandler(
ctx context.Context,
chEvHandler chan Event, predicateFn func(p *Page) (bool, error),
out chan<- any, errOut chan<- error,
) {
b.logger.Debugf("BrowserContext:runWaitForEventHandler:go():starts", "bctxid:%v", b.id)
defer b.logger.Debugf("BrowserContext:runWaitForEventHandler:go():returns", "bctxid:%v", b.id)View on GitHub (pinned to 93accf6570)
Solutions
- Perform the action that opens the new page after calling waitForEvent (waitForEvent resolves concurrently; the click/trigger must actually run), e.g. click the target=_blank link next.
- Pass a larger timeout in the options/predicate argument, e.g. waitForEvent('page', { timeout: 60_000 }).
- Debug why no page appears: check that popups are allowed, the selector clicked is correct, and look at debug logs for EventBrowserContextPage entries.
- If a predicate is used, verify it can return true (e.g. don't assert a URL the page never has).
Example fix
// before
const pagePromise = ctx.waitForEvent('page');
// nothing opens a new page -> timeout
// after
const pagePromise = ctx.waitForEvent('page', { timeout: 30000 });
await page.click('a[target="_blank"]'); // triggers the new tab
const newPage = await pagePromise; Defensive patterns
Strategy: try-catch
Try / catch
try {
const newPage = await context.waitForEvent('page', { timeout: 30000 });
} catch (e) {
if (e.message.includes('timed out')) {
// no new page appeared: check the trigger action, popup settings, or raise the timeout
} else {
throw e;
}
} Prevention
- Always perform the action that opens the new page after registering the wait.
- Set an explicit timeout sized to the app's worst-case page-open time.
- Verify popups are permitted in the browser context when the new page comes from target=_blank or window.open.
- Keep predicates permissive so the wait doesn't depend on exact page state.
When it happens
Trigger: Calling browserContext.waitForEvent('page', { timeout }) when no new page/tab is opened in the context during the timeout window, or when the predicate passed as the second argument never returns true for the pages that do open. Note waitForEvent does not itself open anything: your script must trigger the new page (e.g. click a link with target=_blank).
Common situations: Forgetting to perform the action that opens the new tab after registering the wait; a popup blocked by the browser (popup blocker, permission denied); the triggering click failing silently; timeout too short for a slow page under load; predicate conditions that never match.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- incorrect event %q, %q is the only event supported
- predicate function failed: %w
- browser.on promise rejected: %w
- on create page event failed to return a page: %w
- waiting for page %s event: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/ffaaf83cd4e70882.
Report an issue: GitHub.