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 != nil

View on GitHub (pinned to 93accf6570)

Solutions

  1. Await the navigation (waitForNavigation / waitForLoadState) before querying
  2. Retry the query once after the load state settles
  3. Stop using frames after removing their iframe element
  4. 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

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


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/fb7d226c6391075c. Report an issue: GitHub.