t8y2/dbx · error · RuntimeError
agent exited before {method}
Error message
agent exited before {method} What it means
call() refuses to send a JSON-RPC request when the agent subprocess has already terminated, raising RuntimeError with the stderr tail. This prevents hangs or broken pipes when the child process died between calls. It is raised eagerly at the start of call(), before any request is written.
Source
Thrown at agents/drivers/hive-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 the stderr tail in the error message and any earlier log lines to find why the agent exited (OOM, panic, unhandled exception)
- Check dmesg / container logs for OOM kills and raise the memory limit
- Rerun with a smaller workload to isolate the crashing operation
- Update/fix the agent so the failing method returns an RPC error instead of dying
Defensive patterns
Strategy: try-catch
Validate before calling
def ensure_alive(process) -> None:
if process.exited.is_set():
raise SystemExit(
"agent already exited: " + "\n".join(process.stderr_lines[-20:])
)
ensure_alive(process) # before issuing RPCs Type guard
def agent_alive(process) -> bool:
return not process.exited.is_set() and process.poll() is None Try / catch
try:
result = process.call("execute_query", params)
except RuntimeError as e:
if "agent exited before" in str(e):
print(e) # stderr tail shows crash cause
process = restart_agent()
result = process.call("execute_query", params)
else:
raise Prevention
- Monitor the agent's memory usage; OOM-killed children show up as this error
- Check dmesg/container logs for OOM kills when it recurs
- Validate RPC inputs so the agent never crashes on malformed requests
- Treat 'agent exited' as terminal: restart the process rather than retrying on the dead one
When it happens
Trigger: Invoking any RPC (execute_query, execute_query_page, close, etc.) after the agent process exited — due to a crash on a previous call, OOM-kill of the subprocess, or an explicit terminate from an earlier failure path.
Common situations: Agent killed by OOM killer during a memory-heavy benchmark; agent segfaulted on malformed input; harness bug double-closing a session; running the bench in a container with a low memory limit where the child is reaped.
Related errors
- agent exited before {method}
- agent exited before ready
- agent exited during {method}
- timed out during {method}
- {self.candidate.name} {method}: {json.dumps(response['error'
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/f09ae7559e771204.
Report an issue: GitHub.