{"record":{"id":"d7e72fbd3a03fb7b","repo":"headroomlabs-ai/headroom","slug":"headroom-proxy-startup-is-disabled","errorCode":null,"errorMessage":"Headroom proxy startup is disabled","messagePattern":"Headroom proxy startup is disabled","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugins/openclaw/src/engine.ts","lineNumber":337,"sourceCode":"    // a missing proxy cannot become a process-level unhandled rejection.\n    void this.proxyStartupPromise.catch(() => {});\n  }\n\n  onProxyReady(listener: (proxyUrl: string) => void | Promise<void>): () => void {\n    this.proxyReadyListeners.add(listener);\n    return () => {\n      this.proxyReadyListeners.delete(listener);\n    };\n  }\n\n  async ensureProxyUrl(): Promise<string> {\n    if (this.proxyUrl) {\n      return this.proxyUrl;\n    }\n\n    this.ensureProxyStarted();\n    if (!this.proxyStartupPromise) {\n      throw new Error(\"Headroom proxy startup is disabled\");\n    }\n    return this.proxyStartupPromise;\n  }\n\n  private async notifyProxyReady(proxyUrl: string): Promise<void> {\n    for (const listener of this.proxyReadyListeners) {\n      try {\n        await listener(proxyUrl);\n      } catch (error) {\n        this.logger.warn(`Headroom proxy ready listener failed: ${error}`);\n      }\n    }\n  }\n}\n","sourceCodeStart":319,"sourceCodeEnd":352,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/plugins/openclaw/src/engine.ts#L319-L352","documentation":"ensureProxyUrl() on the OpenClaw engine requires a Headroom proxy, but no proxy URL has been resolved yet and auto-start did not produce a startup promise. ensureProxyStarted() only creates proxyStartupPromise when auto-start is enabled/configured; when it is disabled, the method throws this error immediately. It means the caller wants proxy routing without having provided a running proxy or enabled the engine to start one.","triggerScenarios":"Calling engine.ensureProxyUrl() when engine.proxyUrl is unset (no proxy previously resolved) and the engine's configuration has proxy start/autoStart disabled, so ensureProxyStarted() leaves proxyStartupPromise undefined.","commonSituations":"Integrating OpenClaw with an externally managed Headroom proxy but forgetting to configure its URL; disabling autoStart in a locked-down environment and then calling an API that transparently needs the proxy; ordering bug where ensureProxyUrl is called before the config that enables startup is applied.","solutions":["Enable proxy auto-start in the engine configuration so ensureProxyStarted() creates a startup promise","Or point the engine at an already-running proxy (set proxyUrl in config / resolve it via the proxy manager first) so ensureProxyUrl returns the cached URL","Or start the Headroom proxy out-of-band and register its URL with the engine before any code path calls ensureProxyUrl()"],"exampleFix":"// before: autoStart not enabled, no proxyUrl set\nawait engine.ensureProxyUrl(); // throws\n\n// after: either enable autoStart\nengine.configure({ proxy: { autoStart: true } });\nawait engine.ensureProxyUrl();\n\n// or supply a running proxy explicitly\nengine.configure({ proxy: { proxyUrl: \"http://127.0.0.1:8787\" } });","handlingStrategy":"validation","validationCode":"// Call before any code path can hit ensureProxyUrl()\nfunction canEnsureProxy(engine: { proxyUrl?: string }, config: { autoStart?: boolean }): boolean {\n  return Boolean(engine.proxyUrl) || config.autoStart === true;\n}\n\nif (!canEnsureProxy(engine, engineConfig)) {\n  throw new Error(\"Configure proxyUrl or enable autoStart before requesting the proxy\");\n}","typeGuard":"function isProxyReady(engine: { proxyUrl?: string }): engine is { proxyUrl: string } {\n  return typeof engine.proxyUrl === \"string\" && engine.proxyUrl.length > 0;\n}","tryCatchPattern":"try {\n  const url = await engine.ensureProxyUrl();\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"startup is disabled\")) {\n    // config gap: enable autoStart or provide a running proxy URL\n    throw new Error(\"Proxy required but auto-start disabled: set proxyUrl or autoStart\");\n  }\n  throw e;\n}","preventionTips":["Validate at construction time: assert config has either proxyUrl or autoStart enabled","Resolve the proxy URL once during startup and fail fast, instead of lazily inside request paths","Add a config schema check that rejects 'no proxyUrl and autoStart false' combinations early"],"tags":["proxy","configuration","typescript","openclaw"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}