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
- Confirm the Playwright browser extension is installed, enabled, and has the required permissions (re-grant if prompted).
- Retry the operation after the extension connection is fully established (await `establishExtensionConnection`).
- Check for enterprise/policy restrictions on `chrome.tabs.create` in the managed browser.
- 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
- Ensure the extension is installed, enabled, and granted tabs/debugger permissions.
- Await establishExtensionConnection before driving tabs.
- Reconnect if the extension was reloaded/updated mid-session.
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
- No attached tab to forward browser-level command: ${method}
- No tab found for sessionId: ${sessionId}
- Extension not connected
- Unsupported channel: "${this._browserChannel}"
- "${this._browserChannel}" executable not found. Make sure it
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/e8e017d6aa6b6c6a.
Report an issue: GitHub.