headroomlabs-ai/headroom · critical · RuntimeError
headroom proxy exited with code {self._process.returncode}
Error message
headroom proxy exited with code {self._process.returncode} What it means
Raised while waiting for the headroom proxy subprocess to become healthy: the readiness poll in _wait_ready() noticed the child process had already terminated (poll() returned a non-None exit code). The message includes the process return code; the proxy's log file (opened by the harness) usually contains the real crash reason.
Source
Thrown at headroom/testing/harness.py:1499
if process is not None and process.poll() is None:
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
process.kill()
process.wait(timeout=5)
if self._log_file is not None:
self._log_file.close()
self._log_file = None
def _wait_ready(self) -> None:
assert self._process is not None
url = f"http://127.0.0.1:{self.port}{self.ready_path}"
deadline = time.monotonic() + self.timeout_s
last_error: str | None = None
while time.monotonic() < deadline:
if self._process.poll() is not None:
raise RuntimeError(f"headroom proxy exited with code {self._process.returncode}")
try:
with urllib.request.urlopen(url, timeout=0.5) as response:
if response.status == 200:
return
except (OSError, urllib.error.URLError) as exc:
last_error = str(exc)
time.sleep(0.25)
raise TimeoutError(f"headroom proxy was not ready at {url}: {last_error}")
class _NoopClient:
"""Minimal original-client object for SDK simulations without upstream I/O."""
class ScenarioOrchestrator:
"""Runs built scenarios against local no-key tasks and evaluates guarantees."""
def __init__(View on GitHub (pinned to 322425c43b)
Solutions
- Read the proxy log file the harness captured (it closes _log_file on stop) for the traceback/exit reason.
- Reproduce the spawn command manually (scenario.proxy_command() builds it) and run it in your shell to see stderr.
- If the port is taken (returncode != 0 right after bind), free the port or configure proxy_config.port to another value.
- Verify required env vars/credentials and that the headroom CLI version matches the harness.
Example fix
# before proxy = HeadroomProxy(command=..., port=8080) proxy.start() # RuntimeError: exited with code 1 # after import subprocess, tempfile log = tempfile.NamedTemporaryFile(delete=False) proc = subprocess.Popen(command, stdout=log, stderr=subprocess.STDOUT) proc.wait(); print(open(log.name).read()) # inspect crash, fix cause, then restart
Defensive patterns
Strategy: fallback
Validate before calling
import socket
with socket.socket() as s:
s.bind(("127.0.0.1", port)) # raises if port taken; pick another before starting Try / catch
try:
proxy.start()
except RuntimeError as e:
if "exited with code" in str(e):
log = proxy._log_path or "proxy.log"
raise RuntimeError(f"proxy crashed at startup; see {log}: {e}") from e
raise Prevention
- Always capture the proxy log file path and surface it on failure.
- Smoke-test the proxy command manually when flags/env change.
- Ensure credentials and the headroom CLI version match the harness.
- Free or randomize the port between runs.
When it happens
Trigger: Starting the proxy process via the harness with a bad flag, missing dependency, or missing provider credentials so it exits during startup; port already in use causing immediate exit; incompatible Python/interpreter used to spawn the proxy.
Common situations: CI runners without ANTHROPIC_API_KEY/OPENAI_API_KEY; stale port binding from a previous crashed run; upgrading headroom where CLI flags changed while the harness pins old ones; the headroom package not importable in the spawned interpreter.
Related errors
- Proxy exited with code {proc.returncode}: {tail}
- headroom proxy was not ready at {url}: {last_error}
- Proxy failed to start on port {port} within {timeout_seconds
- recommendations IO error at {path}: {source}
- bedrock_eventstream_parse_failed
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/e98fcde4e15f2718.
Report an issue: GitHub.