microsoft/playwright · error · Error

Launching more browsers is not allowed.

Error message

Launching more browsers is not allowed.

What it means

Thrown by BrowserTypeDispatcher.launch() when _denyLaunch is true. The Playwright server (playwrightServer / launchServer / connect / preLaunchedBrowser modes) sets denyLaunch=true on the BrowserTypeDispatcher once the server itself owns browser lifecycle, so clients cannot spawn additional browsers. This is the launch path (non-persistent).

Source

Thrown at packages/playwright-core/src/server/dispatchers/browserTypeDispatcher.ts:40

import type { BrowserType } from '../browserType';
import type { RootDispatcher } from './dispatcher';
import type * as channels from '../channels';
import type { Progress } from '../progress';

export class BrowserTypeDispatcher extends Dispatcher<BrowserType, channels.BrowserTypeChannel, RootDispatcher> implements channels.BrowserTypeChannel {
  _type_BrowserType = true;
  private readonly _denyLaunch: boolean;
  constructor(scope: RootDispatcher, browserType: BrowserType, denyLaunch: boolean) {
    super(scope, browserType, 'BrowserType', {
      executablePath: browserType.executablePath(),
      name: browserType.name()
    });
    this._denyLaunch = denyLaunch;
  }

  async launch(params: channels.BrowserTypeLaunchParams, progress: Progress): Promise<channels.BrowserTypeLaunchResult> {
    if (this._denyLaunch)
      throw new Error(`Launching more browsers is not allowed.`);

    const browser = await this._object.launch(progress, params);
    return { browser: new BrowserDispatcher(this, browser) };
  }

  async launchPersistentContext(params: channels.BrowserTypeLaunchPersistentContextParams, progress: Progress): Promise<channels.BrowserTypeLaunchPersistentContextResult> {
    if (this._denyLaunch)
      throw new Error(`Launching more browsers is not allowed.`);

    const browserContext = await this._object.launchPersistentContext(progress, params.userDataDir, params);
    const browserDispatcher = new BrowserDispatcher(this, browserContext._browser);
    const contextDispatcher = BrowserContextDispatcher.from(browserDispatcher, browserContext);
    return { browser: browserDispatcher, context: contextDispatcher };
  }

  async connectOverCDP(params: channels.BrowserTypeConnectOverCDPParams, progress: Progress): Promise<channels.BrowserTypeConnectOverCDPResult> {
    if (this._denyLaunch)
      throw new Error(`Launching more browsers is not allowed.`);

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Use the browser the server already gave you: read preLaunchedBrowser from the init result instead of calling launch().
  2. If you need the client to launch, run against a plain local playwright instance rather than a denyLaunch server endpoint.
  3. Confirm the connection mode you are using (connect/launchServer/preLaunched) and align expectations: only the non-denyLaunch path allows launch().

Example fix

// before: launch over a managed server connection
const browser = await chromium.connect(wsEndpoint);
const extra = await chromium.launch(); // denied

// after: reuse the server-provided browser
const { browser } = await chromium.connect(wsEndpoint);
const context = await browser.newContext();
Defensive patterns

Strategy: validation

Validate before calling

const init = await playwright.initialize();
if (init.denyLaunch) throw new Error('Server denies launch(); use init.preLaunchedBrowser instead');

Type guard

function hasPreLaunchedBrowser(init: any): init is { preLaunchedBrowser: Browser } {
  return !!init?.preLaunchedBrowser;
}

Try / catch

try {
  await chromium.launch();
} catch (e) {
  if (/Launching more browsers is not allowed/.test(e.message)) { /* use preLaunchedBrowser */ }
  else throw e;
}

Prevention

When it happens

Trigger: Calling chromium.launch() / firefox.launch() / webkit.launch() over a connection to a Playwright server whose initialize result carried denyLaunch=true (launchServer mode, connect mode, preLaunchedBrowser mode, or launchServerShared). The check fires immediately before any browser process starts.

Common situations: Connecting to a remote browser server (playwright.launchServer / browserType.connectOverCDP to a managed endpoint) and then calling launch() again from the client; MCP/remote sessions that already receive a preLaunchedBrowser but still try to spawn their own; misreading 'connect' as 'launch'.

Related errors


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