{"record":{"id":"05453823c32175a7","repo":"can1357/oh-my-pi","slug":"connected-to-cdpurl-but-puppeteer-connect-faile","errorCode":null,"errorMessage":"Connected to ${cdpUrl} but puppeteer.connect failed: ${(err as Error).message}","messagePattern":"Connected to (.+?) but puppeteer\\.connect failed: (.+?)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/registry.ts","lineNumber":304,"sourceCode":"\t\t} catch (err) {\n\t\t\tawait gracefulKillTreeOnce(child.pid).catch(() => undefined);\n\t\t\tif (err instanceof ToolAbortError) throw err;\n\t\t\tif (err instanceof Error && err.name === \"AbortError\") throw err;\n\t\t\tthrow new ToolError(`Failed to attach to ${path.basename(exe)} on ${cdpUrl}: ${(err as Error).message}`);\n\t\t}\n\t}\n\n\tconst puppeteer = await loadPuppeteer();\n\tlet browser: Browser;\n\ttry {\n\t\tbrowser = await puppeteer.connect({\n\t\t\tbrowserURL: cdpUrl,\n\t\t\tdefaultViewport: null,\n\t\t\tprotocolTimeout: BROWSER_PROTOCOL_TIMEOUT_MS,\n\t\t});\n\t} catch (err) {\n\t\tif (subprocess) await gracefulKillTreeOnce(subprocess.pid);\n\t\tthrow new ToolError(`Connected to ${cdpUrl} but puppeteer.connect failed: ${(err as Error).message}`);\n\t}\n\treturn {\n\t\tkey: browserKey(kind),\n\t\tkind,\n\t\tbrowser,\n\t\tcdpUrl,\n\t\tpid,\n\t\tsubprocess,\n\t\trefCount: 0,\n\t\tstealth: { browserSession: null, override: null },\n\t};\n}\n\nexport function holdBrowser(handle: BrowserHandle): void {\n\thandle.refCount++;\n}\n\nexport async function releaseBrowser(handle: BrowserHandle, opts: ReleaseBrowserOptions): Promise<void> {","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/registry.ts#L286-L322","documentation":"The CDP endpoint answered (waitForCdp succeeded) but puppeteer.connect({browserURL}) failed — e.g. the discovery endpoint returned malformed targets, the browser dropped the connection, or a protocol/timeout error occurred. openBrowserHandle kills the spawned subprocess (if it started one) and wraps the puppeteer error message in ToolError.","triggerScenarios":"CDP HTTP endpoint is up but the DevTools websocket handshake fails: mismatched browser version vs bundled puppeteer, endpoint serving a non-Chrome target, flaky network to a remote cdpUrl, or protocolTimeout (BROWSER_PROTOCOL_TIMEOUT_MS) exceeded during connect.","commonSituations":"Remote debugging over SSH tunnels/containers with dropped connections; Electron-based 'browser' apps with incomplete CDP support; puppeteer version incompatibility with a very new/old Chrome; proxy env vars interfering with the ws upgrade.","solutions":["Retry the open — transient protocol timeouts often succeed on a second attempt","Verify the endpoint really is Chrome CDP: curl http://<cdpUrl>/json/version and check the Browser field","Update the browser binary or the package so puppeteer and Chrome versions are compatible","Check for proxies (HTTP_PROXY/HTTPS_PROXY/NO_PROXY) intercepting localhost websockets"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight: confirm a real Chrome CDP discovery endpoint\nconst info = await fetch(`${cdpUrl}/json/version`).then(r => r.json()).catch(() => null);\nif (!info || !String(info.Browser ?? \"\").includes(\"Chrome\")) {\n  console.error(`${cdpUrl} is not a Chrome CDP endpoint`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const handle = await openBrowserHandle(kind, { signal });\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes(\"puppeteer.connect failed\")) {\n    await Bun.sleep(1000); // transient protocol timeouts often clear\n    return openBrowserHandle(kind, { signal });\n  }\n  throw err;\n}","preventionTips":["Exclude localhost from HTTP(S)_PROXY env vars (NO_PROXY=127.0.0.1,localhost)","Keep puppeteer and the target browser version-compatible","Don't point browserURL at Electron/other apps with partial CDP support","Allow generous protocolTimeout for slow machines/remote endpoints"],"tags":["browser","puppeteer","cdp","protocol","connection"],"backgroundTag":"puppeteer-connect-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}