{"record":{"id":"2de979a8f2b53344","repo":"microsoft/playwright","slug":"playwright-extension-did-not-connect-within-exte","errorCode":null,"errorMessage":"Playwright extension did not connect within ${extensionConnectionTimeout / 1000}s after opening the connect page. Make sure the extension is installed in the Chrome profile${profile} and PLAYWRIGHT_MCP_EXTENSION_TOKEN matches its token.","messagePattern":"Playwright extension did not connect within (.+?)s after opening the connect page\\. Make sure the extension is installed in the Chrome profile(.+?) and PLAYWRIGHT_MCP_EXTENSION_TOKEN matches its token\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/tools/mcp/cdpRelay.ts","lineNumber":143,"sourceCode":"  }\n\n  extensionEndpoint() {\n    return `${this._wsHost}${this._extensionPath}`;\n  }\n\n  async establishExtensionConnection(clientName: string) {\n    debugLogger('Establishing extension connection');\n    await this._openConnectPageInBrowser(clientName);\n    debugLogger('Waiting for incoming extension connection');\n    // Without a token the user has to approve the connection in the browser, which can take arbitrarily long.\n    const deadline = this._token ? monotonicTime() + extensionConnectionTimeout : 0;\n    const { timedOut } = await raceAgainstDeadline(async () => {\n      await this._extensionConnectionPromise;\n      await this._handler.ready();\n    }, deadline);\n    if (timedOut) {\n      const profile = this._profileDirectory ? ` \"${this._profileDirectory}\"` : '';\n      throw new Error(`Playwright extension did not connect within ${extensionConnectionTimeout / 1000}s after opening the connect page. Make sure the extension is installed in the Chrome profile${profile} and PLAYWRIGHT_MCP_EXTENSION_TOKEN matches its token.`);\n    }\n    debugLogger('Extension connection established');\n  }\n\n  private async _openConnectPageInBrowser(clientName: string) {\n    const mcpRelayEndpoint = `${this._wsHost}${this._extensionPath}`;\n    const url = new URL(`chrome-extension://${playwrightExtensionId}/connect.html`);\n    url.searchParams.set('mcpRelayUrl', mcpRelayEndpoint);\n    const client = {\n      name: clientName,\n      // Not used anymore.\n      version: undefined,\n    };\n    url.searchParams.set('client', JSON.stringify(client));\n    url.searchParams.set('protocolVersion', this._protocolVersion.toString());\n    if (this._token)\n      url.searchParams.set('token', this._token);\n    const href = url.toString();","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/microsoft/playwright/blob/312030cdcee20c006343e5f8420fe451b9aa6390/packages/playwright-core/src/tools/mcp/cdpRelay.ts#L125-L161","documentation":"`establishExtensionConnection` waits (against a deadline) for the Playwright Chrome extension to connect to the MCP CDP relay after the connect page is opened. If the extension has not connected and signaled readiness before `extensionConnectionTimeout` elapses, the wait times out and this error is thrown, telling the user to check the extension installation and token.","triggerScenarios":"Calling the MCP extension browser flow (`createExtensionBrowser` → `establishExtensionConnection`) where: the Playwright extension is not installed in the Chrome profile, the extension is installed but disabled, the extension's token does not match `PLAYWRIGHT_MCP_EXTENSION_TOKEN`, the extension fails to reach the relay's WebSocket endpoint, or the profile simply takes longer than the timeout to load.","commonSituations":"First-run setups where the extension was never installed into the profile; setting a custom `PLAYWRIGHT_MCP_EXTENSION_TOKEN` without updating the extension; firewalled/ proxied environments blocking the local WebSocket; slow CI machines exceeding the connection timeout.","solutions":["Verify the Playwright extension is installed and enabled in the Chrome profile (path printed in the error if a custom profile is used).","Ensure the `PLAYWRIGHT_MCP_EXTENSION_TOKEN` environment variable matches the extension's token.","Check debug logs (`DEBUG=pw:mcp`) to confirm the relay endpoint URL and that the extension is attempting to connect.","Make sure no proxy/firewall blocks the local WebSocket endpoint used by the extension.","Retry on a faster machine or free CPU — slow profile startup can exceed the connection timeout."],"exampleFix":"// before\nPLAYWRIGHT_MCP_EXTENSION_TOKEN=wrong-token npx @playwright/mcp\n// after\nPLAYWRIGHT_MCP_EXTENSION_TOKEN=<token-shown-by-extension> npx @playwright/mcp","handlingStrategy":"validation","validationCode":"if (!isExtensionInstalledInProfile(profilePath)) {\n  throw new Error(`Install the Playwright extension in ${profilePath} before starting the MCP extension browser.`);\n}\nif (process.env.PLAYWRIGHT_MCP_EXTENSION_TOKEN && !tokenMatchesExtension(process.env.PLAYWRIGHT_MCP_EXTENSION_TOKEN)) {\n  throw new Error('PLAYWRIGHT_MCP_EXTENSION_TOKEN does not match the extension token.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await establishExtensionConnection(deadline);\n} catch (e) {\n  if (String(e.message).includes('extension did not connect within')) {\n    console.error('Check extension install and PLAYWRIGHT_MCP_EXTENSION_TOKEN; retrying once...');\n    await establishExtensionConnection(newDeadline);\n  } else throw e;\n}","preventionTips":["Install and enable the extension in the Chrome profile before launching the MCP server.","Keep PLAYWRIGHT_MCP_EXTENSION_TOKEN in sync with the extension's token.","Verify with DEBUG=pw:mcp that the relay endpoint is reachable (no proxy/firewall blocking localhost WebSockets).","Avoid resource-starved environments where profile startup exceeds the connection timeout."],"tags":["mcp","extension","timeout","websocket"],"backgroundTag":"request-timeout","analyzedSha":"312030cdcee20c006343e5f8420fe451b9aa6390","analyzedAt":"2026-09-07T14:42:43.271Z","contentChangedAt":"2026-09-07T14:42:43.271Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}