{"record":{"id":"4fed44a28a3884b7","repo":"grafana/k6","slug":"disposing-browser-context-id-s-w","errorCode":null,"errorMessage":"disposing browser context ID %s: %w","messagePattern":"disposing browser context ID (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/js/modules/k6/browser/common/browser.go","lineNumber":178,"sourceCode":"\t\treturn fmt.Errorf(\"connecting to browser DevTools URL: %w\", err)\n\t}\n\n\t// We don't need to lock this because `connect()` is called only in NewBrowser\n\tb.defaultContext, err = NewBrowserContext(b.vuCtx, b, \"\", DefaultBrowserContextOptions(), b.logger)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"browser connect: %w\", err)\n\t}\n\tb.runOnClose = append(b.runOnClose, b.defaultContext.cleanup)\n\n\treturn b.initEvents()\n}\n\nfunc (b *Browser) disposeContext(id cdp.BrowserContextID) error {\n\tb.logger.Debugf(\"Browser:disposeContext\", \"bctxid:%v\", id)\n\n\taction := target.DisposeBrowserContext(id)\n\tif err := action.Do(cdp.WithExecutor(b.vuCtx, b.conn)); err != nil {\n\t\treturn fmt.Errorf(\"disposing browser context ID %s: %w\", id, err)\n\t}\n\tb.context = nil\n\n\treturn nil\n}\n\n// getDefaultBrowserContextOrMatchedID returns the BrowserContext for the given browser context ID.\n// If the browser context is not found, the default BrowserContext is returned.\nfunc (b *Browser) getDefaultBrowserContextOrMatchedID(id cdp.BrowserContextID) *BrowserContext {\n\tb.contextMu.RLock()\n\tdefer b.contextMu.RUnlock()\n\n\tif b.context == nil || b.context.id != id {\n\t\treturn b.defaultContext\n\t}\n\n\treturn b.context\n}","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/browser.go#L160-L196","documentation":"Returned by Browser.disposeContext when the CDP call target.DisposeBrowserContext fails for the given browser context ID. This runs during context teardown (browser.close() paths), so it typically appears while shutting down a browser whose connection is already degraded or whose context no longer exists server-side. The '%s' is the CDP BrowserContextID.","triggerScenarios":"Calling browser.close() (or context close paths) after the remote Chrome already discarded the context (process restart, another client disposed it); the CDP connection is closed/closing so the action.Do round-trip errors; concurrent close of the same context from two paths.","commonSituations":"Scripts sharing one remote Chrome among multiple k6 instances where one instance disposes a context another is closing; test teardown racing with an iteration timeout; remote Chrome restarted mid-test; usually benign during shutdown but worth aligning ownership of contexts.","solutions":["If seen only at teardown after a connection loss, it is usually harmless — ensure your script tolerates close-time errors","Own each context in exactly one place; do not close the same browser/context from multiple VUs or instances","Increase K6_BROWSER_TIMEOUT if long teardowns exceed it and cause spurious failures","Check remote Chrome stability (restarts) if this appears mid-test rather than at shutdown"],"exampleFix":"// before\n// shared remote browser, both VUs close contexts blindly\nctx.close();\n\n// after\n// single owner closes; others just release references\nif (isOwnerVU) ctx.close();","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await browser.close();\n} catch (e) {\n  const m = String(e.message);\n  if (m.includes('disposing browser context')) {\n    // teardown-time dispose failure; safe to ignore if the browser is going away anyway\n    console.warn('context dispose failed during shutdown:', m);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Give each context exactly one owner that closes it","Expect and tolerate close-time errors when the connection may already be gone","Serialize close operations across VUs sharing a browser"],"tags":["cdp","browser-context","teardown","close","race-condition"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}