jackwener/OpenCLI · warning

[opencli] daemon ping failed: HTTP ${res.status}

Error message

[opencli] daemon ping failed: HTTP ${res.status}

What it means

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).

Source

Thrown at extension/src/background.ts:149

  connectInFlight = attempt.finally(() => {
    connectInFlight = null;
  });
  return connectInFlight;
}

async function connectAttempt(): Promise<void> {
  if (isDaemonSocketActive()) return;

  try {
    // omit credentials so the browser doesn't attach the localhost cookie jar —
    // a large jar can push the request past Node's default header limit and make
    // the daemon answer 431, silently wedging the connect loop forever.
    const res = await fetch(DAEMON_PING_URL, {
      signal: AbortSignal.timeout(1000),
      credentials: 'omit',
    });
    if (!res.ok) {
      console.warn(`[opencli] daemon ping failed: HTTP ${res.status}`);
      scheduleReconnect();
      return; // unexpected response — not our daemon, but keep polling.
    }
    // Daemon is reachable — proceed straight to the WebSocket below.
    reconnectAttempts = 0;
  } catch {
    // Daemon not running is the expected idle state — keep the probe silent to
    // avoid per-poll service-worker noise (see connect() docstring). The 431
    // wedge this fixes is surfaced in the !res.ok branch above.
    scheduleReconnect();
    return; // daemon not running — keep polling until the next daemon spawn.
  }
  if (isDaemonSocketActive()) return;

  let thisWs: WebSocket;
  try {
    const contextId = await getCurrentContextId();
    if (isDaemonSocketActive()) return;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Restart the opencli daemon so it clears header/connection state
  2. Check what else is bound to the daemon port and kill the conflicting process
  3. Clear browser extension state / reload the extension to reset reconnect polling
  4. Bypass any proxy for localhost connections
Defensive patterns

Strategy: retry

Validate before calling

const res = await fetch(DAEMON_PING_URL, { signal: AbortSignal.timeout(1000) }).catch(() => null);
if (!res || !res.ok) await restartDaemon();

Try / catch

try { await connectDaemon(); } catch (e) { scheduleReconnect(); }

Prevention

When it happens

Trigger: 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.

Common situations: Daemon accumulated too many/large headers (431); port collision with another local server; daemon restarting mid-poll; corporate proxy intercepting localhost traffic.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/b56bb2975e3419e5. Report an issue: GitHub.