grafana/k6 · error
waiting for function, polling: %w
Error message
waiting for function, polling: %w
What it means
Thrown by Frame.WaitForFunction when the injected polling script (the helper that repeatedly calls your predicate inside the page) cannot be evaluated or the predicate's evaluation chain fails. The %w wraps the underlying CDP Runtime.evaluate error, so the real cause (JS exception in the predicate, destroyed execution context, or timeout) is in the wrapped message. This is k6's browser module translating a failed in-page polling loop into a Go error.
Source
Thrown at internal/js/modules/k6/browser/common/frame.go:2018
// First evaluate the predicate function itself to get its handle.
opts := evalOptions{forceCallable: false, returnByValue: false}
handle, err := execCtx.eval(apiCtx, opts, js)
if err != nil {
return nil, fmt.Errorf("waiting for function, getting handle: %w", err)
}
// Then evaluate the injected function call, passing it the predicate
// function handle and the rest of the arguments.
opts = evalOptions{forceCallable: true, returnByValue: false}
result, err := execCtx.eval(
apiCtx, opts, pageFn, append([]any{
injected,
handle,
polling,
timeout.Milliseconds(), // The JS value is in ms integers
}, args...)...)
if err != nil {
return nil, fmt.Errorf("waiting for function, polling: %w", err)
}
// prevent passing a non-nil interface to the upper layers.
if result == nil {
return nil, nil //nolint:nilnil
}
return result, nil
}
// WaitForLoadState waits for the given load state to be reached.
// This will unblock if that lifecycle event has already been received.
func (f *Frame) WaitForLoadState(state string, popts *FrameWaitForLoadStateOptions) error {
f.log.Debugf("Frame:WaitForLoadState", "fid:%s furl:%q state:%s", f.ID(), f.URL(), state)
defer f.log.Debugf("Frame:WaitForLoadState:return", "fid:%s furl:%q state:%s", f.ID(), f.URL(), state)
timeoutCtx, timeoutCancel := context.WithTimeout(f.ctx, popts.Timeout)
defer timeoutCancel()
View on GitHub (pinned to 93accf6570)
Solutions
- Wrap the predicate body in try/catch and return false on internal errors so a transient JS error does not abort polling
- Make sure a navigation is not in progress: await page.goto(...) or page.waitForLoadState() before waitForFunction
- Increase the timeout option (default 30s) to cover slow pages
- Read the wrapped (%w) error text: 'context destroyed' points to navigation races, a JS stack points to your predicate
Example fix
// before
page.waitForFunction(() => window.results.length > 0);
// after
page.waitForFunction(
() => { try { return window.results.length > 0; } catch { return false; } },
{ timeout: 60_000, polling: 500 }
); Defensive patterns
Strategy: try-catch
Validate before calling
if (typeof page.waitForFunction !== 'function') throw new Error('page is closed or invalid'); Type guard
function isWaitForFunctionTimeout(e) {
return e instanceof Error && /waiting for function, polling/.test(e.message);
} Try / catch
try {
await page.waitForFunction(() => window.ready === true, { timeout: 60_000, polling: 500 });
} catch (e) {
if (isWaitForFunctionTimeout(e)) { /* re-check condition once, then fail with context */ }
throw e;
} Prevention
- Wrap predicate bodies in try/catch returning false
- Ensure no navigation is in flight before waiting
- Set an explicit timeout larger than the worst observed condition time
When it happens
Trigger: Calling page.waitForFunction(fn, arg, {polling: 'raf'|interval, timeout}) where fn throws a JavaScript exception on every poll; the frame navigates while polling is in flight (execution context destroyed); the timeout expires and the injected script rejects; passing a polling value the injected helper cannot use.
Common situations: A predicate that references a DOM node that disappears during the wait; calling waitForFunction immediately after page.goto while the document is still swapping contexts; very short timeouts on pages where the condition only becomes true late; k6 versions where context-destruction races during navigation surfaced here.
Related errors
- k6/experimental/browser has been graduated, please use k6/br
- predicate function is not callable
- WebSocket endpoint cannot be empty
- can't fetch the page for unknown reason
- errorText
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/fd8166c9e2af4771.
Report an issue: GitHub.