grafana/k6 · warning
disposing browser context ID
Error message
disposing browser context ID %s: %w
What it means
BrowserContext.Close() sends Target.disposeBrowserContext over CDP to tear down the context in the browser. This error wraps the browser rejecting or failing that command. It is most often a teardown-ordering artifact: the context is already gone (double close, browser already closing/closed) or the CDP session itself is dead.
Solutions
- Close each context exactly once, before closing the browser, and await the close
- Track a closed flag per context and skip redundant close calls
- Treat close errors during teardown as warnings: log and continue instead of failing the run
- Check K6_BROWSER_LOG=debug for a preceding EventConnectionClose indicating the browser died first
Example fix
// before
await context.close();
await context.close(); // double close -> disposing browser context ID ...
// after
let closed = false;
async function closeContext() {
if (closed) return;
closed = true;
await context.close();
} Defensive patterns
Strategy: try-catch
Try / catch
// During teardown, tolerate context disposal errors
try {
await context.close();
} catch (e) {
if (/disposing browser context ID/.test(String(e))) {
console.warn('context already disposed or browser gone; ignoring');
} else throw e;
} Prevention
- Close each context exactly once and before browser.close()
- Track closed flags in helpers to prevent double close
- Treat teardown close errors as warnings in reports
When it happens
Trigger: Calling context.close() twice; calling context.close() after browser.close() started; closing a context while the WS connection is already lost (browser crashed); disposing a context id the browser no longer knows.
Common situations: finally blocks that close contexts while k6 teardown also closes the browser; double-close from test helpers; closing contexts during an aborted test run.
Related errors
- adding init script to browser context
- adding web vital init script to new browser context
- adding web vital script to new browser context
- clearing permissions
- disposing browser context
AI-assisted analysis of grafana/k6@3fcf5388d7 (2026-09-20).
Data as JSON: /api/errors/4fed44a28a3884b7.
Report an issue: GitHub.
Appendix: source
Thrown at internal/js/modules/k6/browser/common/browser.go:174
if err != nil {
return fmt.Errorf("browser connect: %w", err)
}
// The connection's recvLoop reads defaultContext through
// connectionOnAttachedToTarget, so publish it under contextMu.
b.contextMu.Lock()
b.defaultContext = defaultContext
b.contextMu.Unlock()
b.runOnClose = append(b.runOnClose, defaultContext.cleanup)
return b.initEvents()
}
func (b *Browser) disposeContext(id cdp.BrowserContextID) error {
b.logger.Debugf("Browser:disposeContext", "bctxid:%v", id)
action := target.DisposeBrowserContext(id)
if err := action.Do(cdp.WithExecutor(b.vuCtx, b.conn)); err != nil {
return fmt.Errorf("disposing browser context ID %s: %w", id, err)
}
b.contextMu.Lock()
b.context = nil
b.contextMu.Unlock()
return nil
}
// getDefaultBrowserContextOrMatchedID returns the BrowserContext for the given browser context ID.
// If the browser context is not found, the default BrowserContext is returned.
func (b *Browser) getDefaultBrowserContextOrMatchedID(id cdp.BrowserContextID) *BrowserContext {
b.contextMu.RLock()
defer b.contextMu.RUnlock()
if b.context == nil || b.context.id != id {
return b.defaultContext
}
View on GitHub (pinned to 3fcf5388d7)