t8y2/dbx · error · RuntimeError
agent exited before {method}
Error message
agent exited before {method} What it means
AgentProcess.call raises this RuntimeError when an RPC method is invoked after the agent subprocess's stdout reader loop ended (the `exited` event is set), meaning the child process died or closed its stdout. The harness refuses to send a request to a dead process and fails fast, attaching captured stderr via _failure for diagnosis.
Source
Thrown at agents/drivers/argo-go/bench/agent_compare.py:80
with self.request_lock:
response_queue = self.pending.get(response_id)
if response_queue is not None:
response_queue.put(response)
self.exited.set()
self.ready.set()
with self.request_lock:
pending = list(self.pending.values())
for response_queue in pending:
response_queue.put(RuntimeError(self._failure("agent process exited")))
def _drain_stderr(self) -> None:
assert self.process.stderr is not None
for line in self.process.stderr:
self.stderr_lines.append(line.rstrip())
def call(self, method: str, params: dict | None = None) -> object:
if self.exited.is_set():
raise RuntimeError(self._failure(f"agent exited before {method}"))
with self.request_lock:
self.request_id += 1
request_id = self.request_id
response_queue: queue.Queue = queue.Queue(maxsize=1)
self.pending[request_id] = response_queue
request = {
"jsonrpc": "2.0",
"id": request_id,
"method": method,
"params": params or {},
}
try:
assert self.process.stdin is not None
with self.write_lock:
self.process.stdin.write(json.dumps(request, separators=(",", ":")) + "\n")
self.process.stdin.flush()
response = response_queue.get(timeout=env_float("BENCH_RPC_TIMEOUT", 180.0))
except queue.Empty as error:View on GitHub (pinned to c0390bff16)
Solutions
- Inspect process.stderr_lines (included in the failure message) for the agent's crash output and fix the underlying crash
- Re-check the agent command/artifact path in BENCH_CANDIDATES and rebuild the agent so it starts cleanly
- Catch RuntimeError in the driver, call close(), and restart AgentProcess for the candidate before retrying the workload
- Raise BENCH_RPC_TIMEOUT or reduce workload size if the agent is being killed by OOM during runs
- Verify the agent still emits a ready line and keeps stdout open for the whole session (protocol regression check)
Example fix
// before
rows = process.call("execute_query", params)
// after
try:
rows = process.call("execute_query", params)
except RuntimeError as e:
if "agent exited before" in str(e):
process = AgentProcess(candidate) # restart crashed agent
rows = process.call("execute_query", params)
else:
raise Defensive patterns
Strategy: try-catch
Validate before calling
if process.exited.is_set():
process = AgentProcess(process.candidate) # restart before calling
rows = process.call("execute_query", params) Type guard
def agent_alive(process) -> bool:
return process.process.poll() is None and not process.exited.is_set() Try / catch
try:
result = process.call(method, params)
except RuntimeError as e:
if "agent exited before" in str(e):
log(process.stderr_lines)
process = AgentProcess(process.candidate)
result = process.call(method, params)
else:
raise Prevention
- Check process.exited / poll() before each call in long benchmark loops
- Capture and persist stderr_lines to diagnose crashes post-mortem
- Set BENCH_RPC_TIMEOUT so hangs are converted to TimeoutError instead of a silently-dead agent
- Monitor for OOM kills (candidate rss_kib) and cap workload sizes
When it happens
Trigger: Any call() to method X after the agent process exited: child crashed on startup or mid-run, closed stdout, was killed (OOM, signal), or a previous call timed out and the process was torn down while execute_workload/close/probe_paging/probe_failure_semantics/benchmark_workload/tdengine_websocket_live_compatibility kept issuing calls.
Common situations: Agent binary built from an incompatible version crashes when given a workload; OOM killer terminates a memory-heavy candidate during long benchmark runs; agent panics on a malformed SQL statement in a failure-semantics probe; PYTHONUNBUFFERED/stdio framing mismatch causes the reader loop to hit EOF early.
Related errors
- agent exited before ready
- agent exited during {method}
- agent exited before {method}
- timed out during {method}
- timed out waiting for agent readiness
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/3493fa7d98c6277e.
Report an issue: GitHub.