microsoft/playwright · error · Error

Server is already started.

Error message

Server is already started.

What it means

`BrowserServer.start` sets `_isStarted=true` and refuses a second invocation. BrowserServer backs `browserType.launchServer` / connect endpoints and is meant to be started exactly once per instance.

Source

Thrown at packages/playwright-core/src/server/browser.ts:220

    if (this.isConnected())
      await progress.race(new Promise(x => this.once(Browser.Events.Disconnected, x)));
  }
}

export class BrowserServer {
  private _browser: Browser;
  private _pipeServer?: PlaywrightPipeServer;
  private _wsServer?: PlaywrightWebSocketServer;
  private _pipeSocketPath?: string;
  private _isStarted = false;

  constructor(browser: Browser) {
    this._browser = browser;
  }

  async start(title: string, options: channels.BrowserStartServerOptions): Promise<{ endpoint: string }> {
    if (this._isStarted)
      throw new Error(`Server is already started.`);
    this._isStarted = true;

    let endpoint: string;
    if (options.host !== undefined || options.port !== undefined) {
      this._wsServer = new PlaywrightWebSocketServer(this._browser, '/' + createGuid());
      endpoint = await this._wsServer.listen(options.port ?? 0, options.host);
    } else {
      this._pipeServer = new PlaywrightPipeServer(this._browser);
      this._pipeSocketPath = await this._socketPath();
      await this._pipeServer.listen(this._pipeSocketPath);
      endpoint = this._pipeSocketPath;
    }

    const browserInfo: BrowserInfo = {
      guid: this._browser.guid,
      browserName: this._browser.options.browserType,
      launchOptions: asClientLaunchOptions(this._browser.options.originalLaunchOptions),
      userDataDir: this._browser.options.userDataDir,

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Track started state yourself and only call start() once
  2. Call `stop()` then create a new BrowserServer rather than re-starting
  3. If you need a fresh endpoint, create a new instance instead of reusing

Example fix

// before
await server.start('t', {});
await server.start('t', {}); // throws

// after
await server.start('t', {});
// ... later
await server.stop();
server = browserType.launchServer();
await server.start('t', {});
Defensive patterns

Strategy: validation

Validate before calling

if (serverStarted) {
  throw new Error('BrowserServer already started; stop() and create a new one to restart.');
}
await server.start(title, opts);
serverStarted = true;

Prevention

When it happens

Trigger: Calling `browserServer.start(...)` twice on the same BrowserServer instance.

Common situations: Reuse logic that inadvertently starts a server twice; warm-start optimization that re-runs startup; buggy lifecycle management that re-invokes start on reconnect.

Related errors


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