{"record":{"id":"8ad44768f7495a68","repo":"headroomlabs-ai/headroom","slug":"attempted-to-start-headroom-proxy-but-it-was-not","errorCode":null,"errorMessage":"Attempted to start Headroom proxy, but it was not reachable at ${startupUrl} (${startedProbe.reason ?? \"unknown\"}).","messagePattern":"Attempted to start Headroom proxy, but it was not reachable at (.+?) \\((.+?)\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/openclaw/src/proxy-manager.ts","lineNumber":137,"sourceCode":"          `Cannot auto-start Headroom at ${startupUrl}: port is in use by a non-Headroom service (${startupProbe.reason ?? \"unknown service\"}).`,\n        );\n      }\n\n      this.logger.info(\n        `No Headroom proxy detected${explicitUrl ? ` at ${startupUrl}` : \" on default local endpoints\"}; attempting to auto-start...`,\n      );\n      await this.startHeadroomProxy(startupUrl, port);\n\n      const startedProbe = await waitForHeadroomProxy(\n        startupUrl,\n        this.config.startupTimeoutMs ?? 20_000,\n      );\n      if (startedProbe.reachable && startedProbe.isHeadroom) {\n        this.proxyUrl = startupUrl;\n        this.logger.info(`Headroom proxy started and reachable at ${startupUrl}`);\n        return startupUrl;\n      }\n      throw new Error(\n        `Attempted to start Headroom proxy, but it was not reachable at ${startupUrl} (${startedProbe.reason ?? \"unknown\"}).`,\n      );\n    }\n\n    if (explicitUrl) {\n      throw new Error(\n        `Headroom proxy not reachable at ${explicitUrl}. Ensure the proxy is running first.`,\n      );\n    }\n\n    throw new Error(\n      `Headroom proxy not detected on default endpoints (${defaultCandidates.join(\", \")}). ` +\n        \"Set proxyUrl explicitly or enable autoStart.\",\n    );\n  }\n\n  private getProxyPort(): number {\n    const rawPort = this.config.proxyPort;","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/plugins/openclaw/src/proxy-manager.ts#L119-L155","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Increase startupTimeoutMs in the proxy manager config (e.g. 60000) for slow machines/CI","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","Kill any half-started detached Headroom processes from earlier attempts before retrying"],"exampleFix":"// before\nmanager.configure({ autoStart: true }); // startupTimeoutMs defaults to 20s\n\n// after\nmanager.configure({ autoStart: true, startupTimeoutMs: 60_000 });","handlingStrategy":"retry","validationCode":"import { waitForHeadroomProxy } from \"./proxy-probe.js\";\n\n// Before relying on the manager, give a slow first start room\nconst ok = await waitForHeadroomProxy(\"http://127.0.0.1:8787\", 60_000);\nif (!ok.reachable || !ok.isHeadroom) {\n  throw new Error(`Headroom did not come up in 60s (${ok.reason}) — check launcher install`);","typeGuard":"interface Probe { reachable: boolean; isHeadroom: boolean; reason?: string }\n\nfunction proxyStarted(probe: Probe): probe is Probe & { reachable: true; isHeadroom: true } {\n  return probe.reachable && probe.isHeadroom;\n}","tryCatchPattern":"for (let attempt = 1; attempt <= 3; attempt++) {\n  try {\n    const url = await manager.resolveProxyUrl();\n    break; // success\n  } catch (e) {\n    const msg = e instanceof Error ? e.message : \"\";\n    if (msg.includes(\"not reachable at\") && attempt < 3) {\n      await sleep(2_000 * attempt); // slow first start — back off and retry\n      continue;\n    }\n    throw e;\n  }\n}","preventionTips":["Raise startupTimeoutMs on CI and cold-cache machines (60s instead of the 20s default)","Verify 'headroom proxy' starts cleanly by hand once per environment so launcher failures surface early","Keep headroom-ai's runtime deps warm (pre-install) in CI images to cut first-start latency"],"tags":["proxy","auto-start","timeout","openclaw"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}