headroomlabs-ai/headroom · error · Error

Attempted to start Headroom proxy, but it was not reachable

Error message

Attempted to start Headroom proxy, but it was not reachable at ${startupUrl} (${startedProbe.reason ?? "unknown"}).

What it means

Auto-start spawned the Headroom launcher, then polled waitForHeadroomProxy for startupTimeoutMs (default 20 000 ms), but the proxy never became reachable-and-identified-as-Headroom. The reason string from the final probe distinguishes 'nothing listening' from 'something answered but not Headroom'. The spawned process is detached, so it keeps running even after this failure.

Source

Thrown at plugins/openclaw/src/proxy-manager.ts:137

          `Cannot auto-start Headroom at ${startupUrl}: port is in use by a non-Headroom service (${startupProbe.reason ?? "unknown service"}).`,
        );
      }

      this.logger.info(
        `No Headroom proxy detected${explicitUrl ? ` at ${startupUrl}` : " on default local endpoints"}; attempting to auto-start...`,
      );
      await this.startHeadroomProxy(startupUrl, port);

      const startedProbe = await waitForHeadroomProxy(
        startupUrl,
        this.config.startupTimeoutMs ?? 20_000,
      );
      if (startedProbe.reachable && startedProbe.isHeadroom) {
        this.proxyUrl = startupUrl;
        this.logger.info(`Headroom proxy started and reachable at ${startupUrl}`);
        return startupUrl;
      }
      throw new Error(
        `Attempted to start Headroom proxy, but it was not reachable at ${startupUrl} (${startedProbe.reason ?? "unknown"}).`,
      );
    }

    if (explicitUrl) {
      throw new Error(
        `Headroom proxy not reachable at ${explicitUrl}. Ensure the proxy is running first.`,
      );
    }

    throw new Error(
      `Headroom proxy not detected on default endpoints (${defaultCandidates.join(", ")}). ` +
        "Set proxyUrl explicitly or enable autoStart.",
    );
  }

  private getProxyPort(): number {
    const rawPort = this.config.proxyPort;

View on GitHub (pinned to 322425c43b)

Solutions

  1. Run the launcher manually with the same arguments (headroom proxy --host 127.0.0.1 --port 8787) and read its startup output — it usually reveals the crash or config error
  2. Increase startupTimeoutMs in the proxy manager config (e.g. 60000) for slow machines/CI
  3. Verify headroom-ai is installed and up to date (npm ls -g headroom-ai or pip show headroom-ai), reinstall if the binary is broken
  4. Kill any half-started detached Headroom processes from earlier attempts before retrying

Example fix

// before
manager.configure({ autoStart: true }); // startupTimeoutMs defaults to 20s

// after
manager.configure({ autoStart: true, startupTimeoutMs: 60_000 });
Defensive patterns

Strategy: retry

Validate before calling

import { waitForHeadroomProxy } from "./proxy-probe.js";

// Before relying on the manager, give a slow first start room
const ok = await waitForHeadroomProxy("http://127.0.0.1:8787", 60_000);
if (!ok.reachable || !ok.isHeadroom) {
  throw new Error(`Headroom did not come up in 60s (${ok.reason}) — check launcher install`);

Type guard

interface Probe { reachable: boolean; isHeadroom: boolean; reason?: string }

function proxyStarted(probe: Probe): probe is Probe & { reachable: true; isHeadroom: true } {
  return probe.reachable && probe.isHeadroom;
}

Try / catch

for (let attempt = 1; attempt <= 3; attempt++) {
  try {
    const url = await manager.resolveProxyUrl();
    break; // success
  } catch (e) {
    const msg = e instanceof Error ? e.message : "";
    if (msg.includes("not reachable at") && attempt < 3) {
      await sleep(2_000 * attempt); // slow first start — back off and retry
      continue;
    }
    throw e;
  }
}

Prevention

When it happens

Trigger: autoStart true, launcher spawn succeeded (no error from startHeadroomProxy), but within startupTimeoutMs the proxy either did not bind yet (slow install, cold npm resolution, first-run setup) or started then crashed, or started on a different host/port than probed.

Common situations: First run on a machine where headroom-ai still needs to download/compile; slow disk or npm global resolution delay; proxy crash on startup due to config error; startupTimeoutMs left at default on slow CI runners; detached leftover process from a previous failed attempt holding state.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/8ad44768f7495a68. Report an issue: GitHub.