{"record":{"id":"24fe1ae2ef147ed2","repo":"microsoft/playwright","slug":"extension-not-connected","errorCode":null,"errorMessage":"Extension not connected","messagePattern":"Extension not connected","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/tools/mcp/cdpRelay.ts","lineNumber":83,"sourceCode":"  private _profileDirectory?: string;\n  private _cdpPath: string;\n  private _extensionPath: string;\n  private _cdpConnection: WebSocket | null = null;\n  private _extensionConnection: ExtensionConnection | null = null;\n  private _protocolVersion: number;\n  private _handler: ExtensionProtocolV2;\n  private _extensionConnectionPromise = new ManualPromise<void>();\n\n  constructor(browserChannel: string, executablePath?: string, customUserDataDir?: string, profileDirectory?: string) {\n    this._browserChannel = browserChannel;\n    this._executablePath = executablePath;\n    this._customUserDataDir = customUserDataDir;\n    this._profileDirectory = profileDirectory;\n    this._protocolVersion = parseInt(process.env.PLAYWRIGHT_EXTENSION_PROTOCOL ?? protocol.VERSION.toString(), 10);\n\n    const sendCommand = (method: string, params: any): Promise<any> => {\n      if (!this._extensionConnection)\n        throw new Error('Extension not connected');\n      return this._extensionConnection.send(method as keyof ExtensionCommandV2, params);\n    };\n    this._handler = new ExtensionProtocolV2(sendCommand);\n\n    const uuid = crypto.randomUUID();\n    this._cdpPath = `/cdp/${uuid}`;\n    this._extensionPath = `/extension/${uuid}`;\n\n    void this._extensionConnectionPromise.catch(logUnhandledError);\n    this._wsServer = new WSServer({\n      onRequest: (request, response) => {\n        response.statusCode = 404;\n        response.end();\n      },\n      onHeaders: () => {},\n      onUpgrade: () => undefined,\n      isAllowedPathname: pathname => pathname === this._cdpPath || pathname === this._extensionPath,\n      onConnection: (request, url, ws) => {","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/tools/mcp/cdpRelay.ts#L65-L101","documentation":"Thrown inside the CdpRelay's `sendCommand` closure whenever a command is dispatched before `this._extensionConnection` has been set (the extension WebSocket has not yet connected). The relay routes every Playwright→extension command through that connection, so a missing connection is a hard precondition failure.","triggerScenarios":"Any CDP/command traffic is generated before `_handleExtensionConnection` has wired up `_extensionConnection`, i.e. before `establishExtensionConnection` resolves. This can happen if Playwright connects to the CDP endpoint and starts sending commands before the extension side has dialed in.","commonSituations":"The user has not yet approved/connected the browser extension; the extension failed to connect (network blocked, wrong token, extension disabled); a race where the CDP client connects and issues commands immediately while the extension handshake is still pending.","solutions":["Complete the extension connection flow first — `await relay.establishExtensionConnection(clientName)` — before driving the browser.","Verify the extension is installed, enabled, and that the connect page was accepted by the user.","If a token is configured (`PLAYWRIGHT_MCP_EXTENSION_TOKEN`), ensure the extension sends the matching token."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Only send commands once the extension connection is established.\nlet extensionReady = false;\nrelay.onExtensionConnected(() => { extensionReady = true; });\nfunction assertExtensionReady() {\n  if (!extensionReady) throw new Error('Extension not connected yet; complete the connect flow first.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await cdpRelay.someCommand(...);\n} catch (e) {\n  if (/Extension not connected/.test((e as Error).message)) {\n    await relay.establishExtensionConnection(clientName); // guide user through connect\n    await cdpRelay.someCommand(...);\n  } else throw e;\n}","preventionTips":["Always await establishExtensionConnection before issuing commands.","Confirm the extension is enabled and the user approved the connect page.","Match the token if PLAYWRIGHT_MCP_EXTENSION_TOKEN is set."],"tags":["extension","cdp-relay","connection","websocket","ordering"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}