grafana/k6 · error
got a nil page frame tree
Error message
got a nil page frame tree
What it means
If Page.getFrameTree succeeds but returns a nil FrameTree (frame_session.go:438), initFrameTree returns this non-wrapped sentinel error. The code comment documents the cause: very short scripts where the page is torn down before initialization completes, so chromium reports no tree. It is a race between page lifetime and session setup.
Source
Thrown at internal/js/modules/k6/browser/common/frame_session.go:438
"sid:%v tid:%v", fs.session.ID(), fs.targetID)
action := cdppage.Enable()
if err := action.Do(cdp.WithExecutor(fs.ctx, fs.session)); err != nil {
return fmt.Errorf("enabling page domain: %w", err)
}
var frameTree *cdppage.FrameTree
var err error
// Recursively enumerate all existing frames in page to create initial in-memory structures
// used for access and manipulation from JS.
action2 := cdppage.GetFrameTree()
if frameTree, err = action2.Do(cdp.WithExecutor(fs.ctx, fs.session)); err != nil {
return fmt.Errorf("getting page frame tree: %w", err)
} else if frameTree == nil {
// This can happen with very short scripts when we might not have enough
// time to initialize properly.
return fmt.Errorf("got a nil page frame tree")
}
// Any new frame may have a child frame, not just mainframes.
fs.handleFrameTree(frameTree, fs.isMainFrame())
if fs.isMainFrame() {
fs.initRendererEvents()
}
return nil
}
func (fs *FrameSession) initIsolatedWorld(name string) error {
fs.logger.Debugf("NewFrameSession:initIsolatedWorld",
"sid:%v tid:%v", fs.session.ID(), fs.targetID)
action := cdppage.SetLifecycleEventsEnabled(true)
if err := action.Do(cdp.WithExecutor(fs.ctx, fs.session)); err != nil {
return fmt.Errorf("enabling page lifecycle events: %w", err)View on GitHub (pinned to 93accf6570)
Solutions
- Give the page work to do before ending the iteration: wait for a selector or lifecycle event instead of exiting instantly
- Move browser.close() after all awaited page operations complete
- Retry once — the race is timing-dependent and usually does not reproduce
Example fix
// before
const page = browser.newPage();
page.goto('https://example.com/');
// iteration ends immediately, init races teardown
// after
const page = browser.newPage();
page.goto('https://example.com/', { waitUntil: 'load' });
page.waitForSelector('h1'); Defensive patterns
Strategy: retry
Try / catch
try {
const page = browser.newPage();
page.goto(url);
} catch (e) {
if (/nil page frame tree/i.test(String(e))) {
// page torn down too fast — retry and let the page settle before exiting
}
} Prevention
- Always wait for something concrete (selector, lifecycle event) before ending an iteration
- Call browser.close() only after all page operations complete
When it happens
Trigger: Scripts that create a page and close it (or the test ends) almost immediately; goto to about:blank followed by instant exit; browser.close() racing page init; k6 iteration ending within milliseconds of page creation.
Common situations: Smoke tests with a single quick goto and immediate exit, timeouts set near zero, or teardown (browser.close) firing while a lazy page/iframe session is still initializing.
Related errors
- frame not found for id %s
- getting page frame tree: %w
- cannot close context as none is active in browser
- element is not attached to the DOM
- getting document element: nil document
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/5d790d0dbf59e322.
Report an issue: GitHub.