{"record":{"id":"f09ae7559e771204","repo":"t8y2/dbx","slug":"agent-exited-before-method-f09ae7","errorCode":null,"errorMessage":"agent exited before {method}","messagePattern":"agent exited before (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"agents/drivers/hive-go/bench/agent_compare.py","lineNumber":80,"sourceCode":"            with self.request_lock:\n                response_queue = self.pending.get(response_id)\n            if response_queue is not None:\n                response_queue.put(response)\n        self.exited.set()\n        self.ready.set()\n        with self.request_lock:\n            pending = list(self.pending.values())\n        for response_queue in pending:\n            response_queue.put(RuntimeError(self._failure(\"agent process exited\")))\n\n    def _drain_stderr(self) -> None:\n        assert self.process.stderr is not None\n        for line in self.process.stderr:\n            self.stderr_lines.append(line.rstrip())\n\n    def call(self, method: str, params: dict | None = None) -> object:\n        if self.exited.is_set():\n            raise RuntimeError(self._failure(f\"agent exited before {method}\"))\n        with self.request_lock:\n            self.request_id += 1\n            request_id = self.request_id\n            response_queue: queue.Queue = queue.Queue(maxsize=1)\n            self.pending[request_id] = response_queue\n        request = {\n            \"jsonrpc\": \"2.0\",\n            \"id\": request_id,\n            \"method\": method,\n            \"params\": params or {},\n        }\n        try:\n            assert self.process.stdin is not None\n            with self.write_lock:\n                self.process.stdin.write(json.dumps(request, separators=(\",\", \":\")) + \"\\n\")\n                self.process.stdin.flush()\n            response = response_queue.get(timeout=env_float(\"BENCH_RPC_TIMEOUT\", 180.0))\n        except queue.Empty as error:","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/hive-go/bench/agent_compare.py#L62-L98","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"def ensure_alive(process) -> None:\n    if process.exited.is_set():\n        raise SystemExit(\n            \"agent already exited: \" + \"\\n\".join(process.stderr_lines[-20:])\n        )\nensure_alive(process)  # before issuing RPCs","typeGuard":"def agent_alive(process) -> bool:\n    return not process.exited.is_set() and process.poll() is None","tryCatchPattern":"try:\n    result = process.call(\"execute_query\", params)\nexcept RuntimeError as e:\n    if \"agent exited before\" in str(e):\n        print(e)  # stderr tail shows crash cause\n        process = restart_agent()\n        result = process.call(\"execute_query\", params)\n    else:\n        raise","preventionTips":["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"],"tags":["subprocess","python","process-crash","rpc"],"backgroundTag":"agent-process-exited","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}