grafana/k6 · error
waiting for function: execution context %q not found
Error message
waiting for function: execution context %q not found
What it means
Frame.waitForFunction() looks up the execution context for the requested world (main or utility) under a read lock; if it is nil you get 'waiting for function: execution context "<world>" not found'. waitForExecutionContext() only waits until f.ctx is done — so if the context never appears before the frame context is cancelled, this error fires. It means the frame has no JS world yet, or no longer has one.
Source
Thrown at internal/js/modules/k6/browser/common/frame.go:1987
}
func (f *Frame) waitForFunction(
apiCtx context.Context, world executionWorld, js string,
polling any, timeout time.Duration, args ...any,
) (any, error) {
f.log.Debugf(
"Frame:waitForFunction",
"fid:%s furl:%q world:%s poll:%s timeout:%s",
f.ID(), f.URL(), world, polling, timeout)
f.waitForExecutionContext(world)
f.executionContextMu.RLock()
defer f.executionContextMu.RUnlock()
execCtx := f.executionContexts[world]
if execCtx == nil {
return nil, fmt.Errorf("waiting for function: execution context %q not found", world)
}
injected, err := execCtx.getInjectedScript(apiCtx)
if err != nil {
return nil, fmt.Errorf("getting injected script: %w", err)
}
pageFn := `
(injected, predicate, polling, timeout, ...args) => {
return injected.waitForPredicateFunction(predicate, polling, timeout, ...args);
}
`
// 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)
}View on GitHub (pinned to 93accf6570)
Solutions
- Ensure the frame is loaded before polling: await frame.waitForLoadState('domcontentloaded') then waitForFunction.
- If polling in iframes, re-fetch the frame by name/url from page.frames() instead of caching.
- Increase the k6 iteration timeout so the wait is not cut off.
- Check page.isClosed()/frame detachment and fail the iteration explicitly with a clearer message.
Example fix
// before
await frame.waitForFunction(() => window.ready === true);
// after
await frame.waitForLoadState('domcontentloaded');
await frame.waitForFunction(() => window.ready === true, { timeout: 30_000 }); Defensive patterns
Strategy: validation
Validate before calling
if (page.isClosed()) throw new Error('page closed');
await frame.waitForLoadState('domcontentloaded');
if (frame.isDetached?.()) throw new Error('frame detached before waitForFunction'); Try / catch
try { await frame.waitForFunction(fn, { timeout: 30_000 }); }
catch (e) { if (/execution context .* not found/.test(e.message)) { /* frame lifecycle: refetch frame, wait, retry once */ } throw e; } Prevention
- Wait for domcontentloaded before polling
- Re-fetch iframes from page.frames() each time; never cache
- Keep k6 iteration timeouts larger than poll timeouts
When it happens
Trigger: waitForFunction called on a frame that is detached, crashed, or whose renderer never created the utility world (very early navigation, about:blank); after page.close(); when the k6 iteration context is cancelled while waiting. Cross-origin iframes where world creation is delayed also hit this.
Common situations: Polling for a condition right after frame acquisition without waiting for load; iframes removed by the page mid-poll; k6 per-iteration timeout cancelling f.ctx while the poller waits.
Related errors
- waitFor retry threshold reached
- getting document element handle: %w
- getting document: %w
- setting content: %w
- getting frame title: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/99169d65f566eda4.
Report an issue: GitHub.