microsoft/playwright · error · Error

Browser is already in use for ${userDataDir}, use --isolated

Error message

Browser is already in use for ${userDataDir}, use --isolated to run multiple instances of the same browser

What it means

Thrown by `createPersistentBrowser` after `isProfileLocked5Times` returns true — meaning the profile's lock file (SingletonLock on Unix, lockfile on Windows) was held by a live process for ~5 seconds of retries. Persistent mode requires exclusive access to the userDataDir, so a locked profile aborts launch. The message directs the user to `--isolated`.

Source

Thrown at packages/playwright-core/src/tools/mcp/browserFactory.ts:164

  const playwrightObject = playwright as Playwright;
  // Use connectToBrowser instead of playwright[browserName].connect because we don't have browserName.
  const browser = await connectToBrowser(playwrightObject, remoteOptions);
  browser._connectToBrowserType(playwrightObject[browser._browserName], {}, undefined);
  // A browser started via `launchServer` exposes no contexts until one is
  // created, so create one when attaching to such a server.
  if (!browser.contexts().length)
    await browser.newContext(config.browser.contextOptions);
  return { browser, browserInfo: browserInfo(browser, config), canBind: false, ownership: 'attached' };
}

async function createPersistentBrowser(config: FullConfig, clientInfo: ClientInfo): Promise<playwrightTypes.Browser> {
  testDebug('create browser (persistent)');
  const userDataDir = config.browser.userDataDir ?? await createUserDataDir(config, clientInfo);
  const tracesDir = await computeTracesDir(config, clientInfo);

  if (await isProfileLocked5Times(userDataDir))
    throw new Error(`Browser is already in use for ${userDataDir}, use --isolated to run multiple instances of the same browser`);

  const browserType = playwright[config.browser.browserName];
  const configIgnoreDefaultArgs = config.browser.launchOptions?.ignoreDefaultArgs;
  const launchOptions: playwrightTypes.LaunchOptions & playwrightTypes.BrowserContextOptions = {
    tracesDir,
    ...config.browser.launchOptions,
    ...config.browser.contextOptions,
    handleSIGINT: false,
    handleSIGTERM: false,
    ignoreDefaultArgs: configIgnoreDefaultArgs === true
      ? true
      : [
        '--disable-extensions',
        ...Array.isArray(configIgnoreDefaultArgs) ? configIgnoreDefaultArgs : [],
      ],
  };
  try {
    const browserContext = await browserType.launchPersistentContext(userDataDir, launchOptions);

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Close the other browser instance using that profile, then retry.
  2. Use `--isolated` so each session gets its own ephemeral context (no shared userDataDir).
  3. If the lock is stale (process died), remove the SingletonLock/lockfile under the userDataDir and retry.
  4. Give each concurrent session a distinct `--user-data-dir` or `--profile`.

Example fix

# before
playwright mcp --user-data-dir ~/.cache/mcp-profile
# (second concurrent invocation fails)
# after
playwright mcp --isolated
Defensive patterns

Strategy: validation

Validate before calling

import { isProfileLocked } from '@tools/mcp/browserFactory';
async function assertProfileFree(userDataDir: string) {
  if (await isProfileLocked(userDataDir))
    throw new Error(`Profile ${userDataDir} is locked by another process; use --isolated.`);
}

Try / catch

try {
  await launchPersistent(opts);
} catch (e) {
  if (/Browser is already in use/.test((e as Error).message)) {
    opts.isolated = true; await launchPersistent(opts); // fall back to isolated
  } else throw e;
}

Prevention

When it happens

Trigger: Launching a persistent browser (non-isolated) against a userDataDir already in use by another running browser instance (another MCP/CLI session, a manually-opened Chrome with the same profile, or a prior crashed process whose lock is held). The pre-launch lock check in `isProfileLocked5Times` polls 5x at 1s intervals.

Common situations: Two MCP clients using the same workspace/profile concurrently; a user has Chrome open with that profile; a previous browser process did not clean up its SingletonLock; running on CI where a parallel job shares the profiles dir.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/f3eb29b7680bbd78. Report an issue: GitHub.