{"record":{"id":"b56bb2975e3419e5","repo":"jackwener/OpenCLI","slug":"opencli-daemon-ping-failed-http-res-status","errorCode":null,"errorMessage":"[opencli] daemon ping failed: HTTP ${res.status}","messagePattern":"\\[opencli\\] daemon ping failed: HTTP (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"extension/src/background.ts","lineNumber":149,"sourceCode":"  connectInFlight = attempt.finally(() => {\n    connectInFlight = null;\n  });\n  return connectInFlight;\n}\n\nasync function connectAttempt(): Promise<void> {\n  if (isDaemonSocketActive()) return;\n\n  try {\n    // omit credentials so the browser doesn't attach the localhost cookie jar —\n    // a large jar can push the request past Node's default header limit and make\n    // the daemon answer 431, silently wedging the connect loop forever.\n    const res = await fetch(DAEMON_PING_URL, {\n      signal: AbortSignal.timeout(1000),\n      credentials: 'omit',\n    });\n    if (!res.ok) {\n      console.warn(`[opencli] daemon ping failed: HTTP ${res.status}`);\n      scheduleReconnect();\n      return; // unexpected response — not our daemon, but keep polling.\n    }\n    // Daemon is reachable — proceed straight to the WebSocket below.\n    reconnectAttempts = 0;\n  } catch {\n    // Daemon not running is the expected idle state — keep the probe silent to\n    // avoid per-poll service-worker noise (see connect() docstring). The 431\n    // wedge this fixes is surfaced in the !res.ok branch above.\n    scheduleReconnect();\n    return; // daemon not running — keep polling until the next daemon spawn.\n  }\n  if (isDaemonSocketActive()) return;\n\n  let thisWs: WebSocket;\n  try {\n    const contextId = await getCurrentContextId();\n    if (isDaemonSocketActive()) return;","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/extension/src/background.ts#L131-L167","documentation":"A console warning from the extension's connectAttempt when the HTTP pre-flight ping to the daemon (DAEMON_PING_URL) returns a non-ok status. The extension treats this as 'daemon reachable but not answering correctly' and schedules a reconnect instead of opening the WebSocket, preventing a permanently wedged connect loop (e.g. after the daemon answers 431).","triggerScenarios":"The daemon HTTP endpoint returns 4xx/5xx (notably 431 Request Header Fields Too Large) during the 1-second-timeout fetch; a proxy or another process is listening on the daemon port and replies with an error status.","commonSituations":"Daemon accumulated too many/large headers (431); port collision with another local server; daemon restarting mid-poll; corporate proxy intercepting localhost traffic.","solutions":["Restart the opencli daemon so it clears header/connection state","Check what else is bound to the daemon port and kill the conflicting process","Clear browser extension state / reload the extension to reset reconnect polling","Bypass any proxy for localhost connections"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const res = await fetch(DAEMON_PING_URL, { signal: AbortSignal.timeout(1000) }).catch(() => null);\nif (!res || !res.ok) await restartDaemon();","typeGuard":null,"tryCatchPattern":"try { await connectDaemon(); } catch (e) { scheduleReconnect(); }","preventionTips":["Restart the daemon periodically or on suspicious 4xx responses","Monitor the daemon port for conflicts","Exclude localhost from proxies","Reload the extension if reconnect polling wedges"],"tags":["daemon","http","connectivity"],"backgroundTag":"daemon-ping-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}