headroomlabs-ai/headroom · critical · RuntimeError
Proxy exited with code {proc.returncode}: {tail}
Error message
Proxy exited with code {proc.returncode}: {tail} What it means
After spawning the proxy subprocess, Headroom polls once per second for up to the configured timeout waiting for the proxy's health check to pass. If the subprocess dies during that window (proc.poll() is not None), it reads the last ~500 chars of the proxy's stdio log for context and raises this RuntimeError with the exit code and log tail. This means the proxy crashed during startup rather than merely being slow.
Source
Thrown at headroom/cli/wrap.py:805
popen_kwargs["creationflags"] = creationflags & ~_CREATE_BREAKAWAY_FROM_JOB
proc = subprocess.Popen(cmd, **popen_kwargs)
# Wait for proxy to be ready.
# ML components (Kompress, Magika, Tree-sitter) load synchronously before
# uvicorn binds the port. On slower machines this can take 20-30 seconds.
for _i in range(timeout_seconds):
time.sleep(1)
if _check_proxy(port):
click.echo(f" Logs: {log_path}")
return proc
# Check if process died
if proc.poll() is not None:
# Read last few lines of log for error context
try:
tail = _read_text(stdio_log_path)[-500:]
except Exception:
tail = "(no log output)"
raise RuntimeError(f"Proxy exited with code {proc.returncode}: {tail}")
proc.kill()
raise RuntimeError(
f"Proxy failed to start on port {port} within {timeout_seconds} seconds. "
f"Set {_WRAP_PROXY_TIMEOUT_ENV} to a larger number of seconds for slow startup."
)
finally:
stdio_log_file.close()
# CLI context tools (rtk, lean-ctx) were removed from Headroom. The selector is
# kept only long enough to fail loudly: it lives in shell profiles, scripts and
# CI jobs, and silently ignoring it would look like Headroom had stopped working.
# See :mod:`headroom.context_tool_cleanup`, which uninstalls what they left behind.
_RETIRED_CONTEXT_TOOL_ENV = "HEADROOM_CONTEXT_TOOL"
_RETIRED_CONTEXT_TOOL_MESSAGE = (
"CLI context tools (rtk, lean-ctx) have been removed from Headroom: they "
"rewrote shell commands through a third-party binary Headroom no longer "View on GitHub (pinned to 322425c43b)
Solutions
- Read the log tail in the message — it contains the proxy's actual crash reason; fix what it names (key, backend name, config)
- Open the full proxy log (path printed as 'Logs: .../proxy.log') for the complete traceback
- Verify credentials are present and valid for the chosen backend (e.g. ANTHROPIC_API_KEY, GITHUB_COPILOT_API_URL env)
- Re-run with --backend explicitly set to a supported value, or update Headroom if the proxy code and CLI are out of sync
Example fix
# before headroom wrap claude --backend litellm-vertix # child dies: unknown backend # RuntimeError: Proxy exited with code 1: ... unknown backend 'litellm-vertix' # after headroom wrap claude --backend litellm-vertex
Defensive patterns
Strategy: try-catch
Validate before calling
import subprocess
def proxy_config_ok() -> bool:
"""Smoke-test the proxy module directly; a non-zero exit predicts a startup crash."""
r = subprocess.run(["python", "-m", "headroom.proxy", "--check"], capture_output=True)
return r.returncode == 0 Try / catch
try:
proc = start_proxy(timeout_seconds=60)
except RuntimeError as e:
msg = str(e)
if msg.startswith("Proxy exited with code"):
# msg already contains the child's log tail; log it for diagnosis
log.error("proxy crashed at startup: %s", msg)
raise SystemExit(1) from e
raise Prevention
- Validate backend names and credentials before starting the wrap
- Keep the proxy.log path handy; check it on any startup failure
- Keep headroom CLI and proxy code in sync (single installed version)
When it happens
Trigger: Calling the proxy-startup routine when the proxy process exits non-zero during boot: invalid proxy configuration, missing credentials for the selected backend, a Python exception in the proxy server, a port conflict at bind time inside the child, or an incompatible backend name passed via --backend. The error surfaces the child's actual log tail, which names the root cause.
Common situations: Expired or missing provider API keys causing the proxy to abort at startup; a typo'd --backend (e.g. litellm-vertix); version mismatch where the proxy module hits an ImportError; the port was free during the scan but taken before the child bound it; stale config files the proxy rejects at boot.
Related errors
- Proxy process exited unexpectedly.
- Proxy failed to start on port {port} within {timeout_seconds
- headroom proxy exited with code {self._process.returncode}
- Error: Proxy dependencies not installed. Run: pip install he
- Shutting down...
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/4405cd5a32ed39ee.
Report an issue: GitHub.