headroomlabs-ai/headroom · error · Error

Headroom proxy not reachable at ${explicitUrl}. Ensure the p

Error message

Headroom proxy not reachable at ${explicitUrl}. Ensure the proxy is running first.

What it means

An explicit local proxyUrl was configured, the probe found nothing (or nothing Headroom-like) there, auto-start is not enabled, so the manager has no way to bring the proxy up and refuses to proceed. This is the connect-only failure for local explicit URLs; it never spawns a process unless autoStart is true.

Source

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

      );
      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;
    if (!Number.isInteger(rawPort) || rawPort === undefined) return 8787;
    if (rawPort < 1 || rawPort > 65535) {
      throw new Error("proxyPort must be an integer between 1 and 65535");
    }
    return rawPort;
  }

View on GitHub (pinned to 322425c43b)

Solutions

  1. Start the proxy at the configured address: headroom proxy --host 127.0.0.1 --port <same-port-as-proxyUrl>
  2. If you want the client to handle startup, enable autoStart in the manager config
  3. Correct a port/host typo in proxyUrl so it matches where Headroom actually listens

Example fix

# before: client configured but proxy never started
manager.configure({ proxyUrl: "http://127.0.0.1:8787" });

# after: start the proxy first, or let the manager do it
headroom proxy --port 8787 &
# or: manager.configure({ proxyUrl: "http://127.0.0.1:8787", autoStart: true });
Defensive patterns

Strategy: validation

Validate before calling

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

const proxyUrl = "http://127.0.0.1:8787";
const probe = await probeHeadroomProxy(proxyUrl);
if (!(probe.reachable && probe.isHeadroom)) {
  throw new Error(`No Headroom proxy at ${proxyUrl} (${probe.reason}); start it or enable autoStart`);

Type guard

interface Probe { reachable: boolean; isHeadroom: boolean }

function isUsableProxy(probe: Probe | null | undefined): probe is Probe & { reachable: true; isHeadroom: true } {
  return Boolean(probe?.reachable && probe?.isHeadroom);
}

Try / catch

try {
  await manager.resolveProxyUrl();
} catch (e) {
  if (e instanceof Error && e.message.includes("Ensure the proxy is running first")) {
    throw new Error("Startup order bug: launch the Headroom proxy before the client (or set autoStart)");
  }
  throw e;
}

Prevention

When it happens

Trigger: proxyUrl set to a local address (e.g. http://127.0.0.1:8787), autoStart unset/false, and no Headroom proxy currently listening at that address — not started, crashed, or listening on a different port.

Common situations: Forgetting to launch 'headroom proxy' before starting the client; proxy crashed in the background; port mismatch between the headroom CLI invocation and the client config; assuming the client auto-starts the proxy when autoStart was explicitly disabled.

Related errors


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