microsoft/playwright · error · Error

Failed to create tab

Error message

Failed to create tab

What it means

Thrown by the extension-backed browser model's `createTarget` after calling `chrome.tabs.create` via the extension, when the returned tab object has no `id` (`tab?.id === undefined`). Without a tab id the new tab cannot be attached or tracked, so the operation is reported as a failure.

Source

Thrown at packages/playwright-core/src/tools/mcp/browserModel.ts:144

  onDebuggerDetach(source: Debuggee): void {
    if (source.tabId !== undefined)
      this._detachTab(source.tabId);
  }

  // ─── Playwright → model commands ──────────────────────────────────────

  // Turn auto-attach on and attach to every tab we already know about.
  // Called in response to Playwright's `Target.setAutoAttach` on the root session.
  async enableAutoAttach(): Promise<void> {
    this._autoAttach = true;
    const tabIds = [...this._knownTabs.keys()];
    await Promise.all(tabIds.map(tabId => this._attachTab(tabId).catch(logUnhandledError)));
  }

  async createTarget(url: string | undefined): Promise<{ targetId: string | undefined }> {
    const tab = await this._sendToExtension('chrome.tabs.create', [{ url }]);
    if (tab?.id === undefined)
      throw new Error('Failed to create tab');
    this._knownTabs.set(tab.id, tab);
    const tabSession = await this._attachTab(tab.id);
    return { targetId: tabSession.targetInfo?.targetId };
  }

  async closeTarget(targetId: string | undefined): Promise<{ success: boolean }> {
    const tabSession = targetId ? this._findTabSession(s => s.targetInfo?.targetId === targetId) : undefined;
    if (!tabSession)
      return { success: false };
    await this._sendToExtension('chrome.tabs.remove', [tabSession.tabId]);
    return { success: true };
  }

  getTargetInfo(sessionId: string | undefined): any {
    if (!sessionId)
      return undefined;
    return this._findTabSession(s => s.sessionId === sessionId)?.targetInfo;
  }

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Confirm the Playwright browser extension is installed, enabled, and has the required permissions (re-grant if prompted).
  2. Retry the operation after the extension connection is fully established (await `establishExtensionConnection`).
  3. Check for enterprise/policy restrictions on `chrome.tabs.create` in the managed browser.
  4. If the extension was updated, reconnect (restart the relay/browser) to get a fresh extension context.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await model.createTarget(url);
} catch (e) {
  if (/Failed to create tab/.test((e as Error).message)) {
    // re-check extension health, then retry once
    await relay.establishExtensionConnection(clientName);
    await model.createTarget(url);
  } else throw e;
}

Prevention

When it happens

Trigger: The extension host rejects `chrome.tabs.create` (permissions not granted, tab blocked by policy, extension context invalidated), or returns a tab object missing the `id` field. Also possible if the extension is in a transient state (just connected, mid-handshake) when create is called.

Common situations: Using the browser-extension connection mode (`--extension`) without granting the `tabs` permission; the extension was reloaded/updated mid-session; an enterprise policy blocks tab creation; calling create immediately after connect before the extension is fully ready.

Related errors


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