grafana/k6 · error
default browser context can't be closed
Error message
default browser context can't be closed
What it means
browser.context() returns chromium's implicit default browser context, whose internal ID is the empty string. BrowserContext.Close (browser_context.go:210) explicitly refuses to close it: 'default browser context can't be closed'. The default context is owned by the browser process and is torn down when the browser closes, so k6 rejects the call outright.
Source
Thrown at internal/js/modules/k6/browser/common/browser_context.go:210
// ClearPermissions clears any permission overrides.
func (b *BrowserContext) ClearPermissions() error {
b.logger.Debugf("BrowserContext:ClearPermissions", "bctxid:%v", b.id)
action := cdpbrowser.ResetPermissions().WithBrowserContextID(b.id)
if err := action.Do(cdp.WithExecutor(b.ctx, b.browser.conn)); err != nil {
return fmt.Errorf("clearing permissions: %w", err)
}
return nil
}
// Close shuts down the browser context.
func (b *BrowserContext) Close() error {
b.logger.Debugf("BrowserContext:Close", "bctxid:%v", b.id)
if b.id == "" {
return fmt.Errorf("default browser context can't be closed")
}
if err := b.browser.disposeContext(b.id); err != nil {
return fmt.Errorf("disposing browser context: %w", err)
}
return nil
}
// GrantPermissions enables the specified permissions, all others will be disabled.
func (b *BrowserContext) GrantPermissions(permissions []string, opts GrantPermissionsOptions) error {
b.logger.Debugf("BrowserContext:GrantPermissions", "bctxid:%v", b.id)
permsToProtocol := map[string]cdpbrowser.PermissionType{
"geolocation": cdpbrowser.PermissionTypeGeolocation,
"midi": cdpbrowser.PermissionTypeMidi,
"midi-sysex": cdpbrowser.PermissionTypeMidiSysex,
"notifications": cdpbrowser.PermissionTypeNotifications,
"camera": cdpbrowser.PermissionTypeVideoCapture,
"microphone": cdpbrowser.PermissionTypeAudioCapture,View on GitHub (pinned to 93accf6570)
Solutions
- Only close contexts you created with browser.newContext()
- Guard the close: skip it when the context is browser.context()
- Rely on browser.close() to tear down the default context and its pages
Example fix
// before const ctx = browser.context() await ctx.close() // throws: default browser context can't be closed // after const ctx = browser.newContext() await ctx.close() // OK // or: let browser.close() clean up the default context
Defensive patterns
Strategy: type-guard
Validate before calling
const isDefault = (ctx) => ctx === browser.context() if (!isDefault(ctx)) await ctx.close()
Type guard
function isDefaultContext(ctx, browser) {
return ctx === browser.context()
} Try / catch
try {
await ctx.close()
} catch (e) {
if (/default browser context can't be closed/.test(String(e))) {
// expected when handed the default context — ignore
} else throw e
} Prevention
- Only close contexts created via newContext()
- Guard shared close helpers against browser.context()
- Let browser.close() clean up the default context
When it happens
Trigger: const ctx = browser.context(); await ctx.close(); — the only way to hit it. Also generic helpers that blindly close every context they are handed, including the default one.
Common situations: Code ported from Playwright, where closing the default context is permitted; scripts that iterate all contexts and close them; shared teardown closing browser.context() alongside user contexts.
Related errors
- missing browser context %s, current context is %s
- disposing browser context: %w
- %q is an invalid permission
- incorrect event %q, %q is the only event supported
- clearing cookies: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/4e49dd7feaffdfae.
Report an issue: GitHub.