grafana/k6 · warning

disposing browser context ID %s: %w

Error message

disposing browser context ID %s: %w

What it means

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.

Source

Thrown at internal/js/modules/k6/browser/common/browser.go:178

		return fmt.Errorf("connecting to browser DevTools URL: %w", err)
	}

	// We don't need to lock this because `connect()` is called only in NewBrowser
	b.defaultContext, err = NewBrowserContext(b.vuCtx, b, "", DefaultBrowserContextOptions(), b.logger)
	if err != nil {
		return fmt.Errorf("browser connect: %w", err)
	}
	b.runOnClose = append(b.runOnClose, b.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.context = nil

	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
	}

	return b.context
}

View on GitHub (pinned to 93accf6570)

Solutions

  1. If seen only at teardown after a connection loss, it is usually harmless — ensure your script tolerates close-time errors
  2. Own each context in exactly one place; do not close the same browser/context from multiple VUs or instances
  3. Increase K6_BROWSER_TIMEOUT if long teardowns exceed it and cause spurious failures
  4. Check remote Chrome stability (restarts) if this appears mid-test rather than at shutdown

Example fix

// before
// shared remote browser, both VUs close contexts blindly
ctx.close();

// after
// single owner closes; others just release references
if (isOwnerVU) ctx.close();
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await browser.close();
} catch (e) {
  const m = String(e.message);
  if (m.includes('disposing browser context')) {
    // teardown-time dispose failure; safe to ignore if the browser is going away anyway
    console.warn('context dispose failed during shutdown:', m);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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