grafana/k6 · error
getting new document handle: %w
Error message
getting new document handle: %w
What it means
Frame.document needs the frame's document element handle; when no cached handle exists it calls newDocumentHandle (which evaluates 'document' in the main world) and wraps any failure with this message. The evaluate fails when the main-world execution context is gone — the frame navigated (contexts are destroyed and recreated on navigation), the frame was detached, or the target is closing.
Source
Thrown at internal/js/modules/k6/browser/common/frame.go:257
return nil
}
func (f *Frame) defaultTimeout() time.Duration {
return f.manager.timeoutSettings.timeout()
}
func (f *Frame) document() (*ElementHandle, error) {
f.log.Debugf("Frame:document", "fid:%s furl:%q", f.ID(), f.URL())
if cdh, ok := f.cachedDocumentHandle(); ok {
return cdh, nil
}
f.waitForExecutionContext(mainWorld)
dh, err := f.newDocumentHandle()
if err != nil {
return nil, fmt.Errorf("getting new document handle: %w", err)
}
// each execution context switch modifies documentHandle.
// see: nullContext().
f.executionContextMu.Lock()
defer f.executionContextMu.Unlock()
f.documentHandle = dh
return dh, nil
}
func (f *Frame) cachedDocumentHandle() (*ElementHandle, bool) {
// each execution context switch modifies documentHandle.
// see: nullContext().
f.executionContextMu.RLock()
defer f.executionContextMu.RUnlock()
return f.documentHandle, f.documentHandle != nilView on GitHub (pinned to 93accf6570)
Solutions
- Await the navigation (waitForNavigation / waitForLoadState) before querying
- Retry the query once after the load state settles
- Stop using frames after removing their iframe element
- Give the action a timeout budget so k6's internal retries can work
Example fix
// before
await page.click('#go');
await page.waitForSelector('#result'); // races the navigation
// after
await Promise.all([page.waitForNavigation(), page.click('#go')]);
await page.waitForSelector('#result'); Defensive patterns
Strategy: retry
Try / catch
async function queryStable(page, sel, tries = 3) {
for (let i = 0; i < tries; i++) {
try { return await page.waitForSelector(sel); }
catch (e) {
if (!/new document handle|Execution context|navigated/.test(e.message) || i === tries - 1) throw e;
await page.waitForLoadState();
}
}
} Prevention
- Synchronize on load state after navigation-triggering actions
- Do not hold frame references across navigations
- Scope per-frame work tightly; re-resolve frames from the page after transitions
When it happens
Trigger: Calling frame/page actions that need the document (waitForSelector, element queries) during a navigation; acting on a frame just detached from the DOM; actions racing page.close().
Common situations: Doing queries immediately after a click-induced navigation without waiting; scripts that keep using a frame after its iframe is removed; shutdown races at iteration end.
Related errors
- document element handle is nil
- getting frame title: expected string, got %T
- missing required argument 'url'
- getting document element: nil document
- waitFor retry threshold reached
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/fb7d226c6391075c.
Report an issue: GitHub.