t8y2/dbx · error · TimeoutError

timed out waiting for agent readiness

Error message

timed out waiting for agent readiness

What it means

The AgentProcess wrapper launches the candidate agent as a subprocess, communicates over JSON-RPC on stdio, and waits on a readiness Event. If the agent does not signal readiness within BENCH_READY_TIMEOUT (default 30s) or exits before signaling, __init__ raises TimeoutError with the captured stderr tail to help diagnose why startup failed.

Source

Thrown at agents/drivers/hive-go/bench/agent_compare.py:46

            candidate.command,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            bufsize=1,
        )
        self.request_id = 0
        self.request_lock = threading.Lock()
        self.write_lock = threading.Lock()
        self.pending: dict[int, queue.Queue] = {}
        self.ready = threading.Event()
        self.saw_ready = False
        self.exited = threading.Event()
        self.stderr_lines: list[str] = []
        threading.Thread(target=self._read_stdout, daemon=True).start()
        threading.Thread(target=self._drain_stderr, daemon=True).start()
        if not self.ready.wait(env_float("BENCH_READY_TIMEOUT", 30.0)) or not self.saw_ready:
            raise TimeoutError(self._failure("timed out waiting for agent readiness"))

    def _read_stdout(self) -> None:
        assert self.process.stdout is not None
        for line in self.process.stdout:
            try:
                response = json.loads(line)
            except json.JSONDecodeError:
                continue
            if response.get("ready") is True:
                self.saw_ready = True
                self.ready.set()
                continue
            response_id = response.get("id")
            if not isinstance(response_id, int):
                continue
            with self.request_lock:
                response_queue = self.pending.get(response_id)
            if response_queue is not None:

View on GitHub (pinned to c0390bff16)

Solutions

  1. Increase BENCH_READY_TIMEOUT (e.g. export BENCH_READY_TIMEOUT=120) and rerun
  2. Read the stderr tail embedded in the error to find the agent's real startup failure (missing jar, bad credentials, port in use)
  3. Verify the agent runs standalone with the same env/args before running the bench
  4. Ensure nothing else prints to the agent's stdout, which would break the readiness handshake

Example fix

// before
BENCH_READY_TIMEOUT=30 python bench/agent_compare.py
// after
BENCH_READY_TIMEOUT=120 python bench/agent_compare.py
Defensive patterns

Strategy: retry

Validate before calling

import subprocess, shutil
def preflight_agent(command: list[str]) -> None:
    if shutil.which(command[0]) is None and not os.path.exists(command[0]):
        raise SystemExit(f"agent executable missing: {command[0]}")
# also verify DB connectivity before launch
# socket.create_connection((host, port), timeout=5)

Try / catch

try:
    agent = AgentProcess(cmd, ...)
except TimeoutError as e:
    print(e)  # includes stderr tail
    # retry once with a larger BENCH_READY_TIMEOUT
    os.environ["BENCH_READY_TIMEOUT"] = "120"
    agent = AgentProcess(cmd, ...)

Prevention

When it happens

Trigger: The agent subprocess starts slowly (JVM warmup, slow image pull, cold page cache), crashes immediately on startup, or blocks waiting on its own dependencies (database connection refused, missing config), so 'ready' is never seen before the timeout.

Common situations: Heavy-traffic CI runners where 30s is too short for a JVM-based agent; misconfigured HIVE_HOST/DB env so the agent exits or hangs; a broken agent build/jar path; startup scripts printing to stdout and corrupting the JSON-RPC channel so the ready message is never parsed.

Understand the failure class

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/c9a9bbc9b367a359. Report an issue: GitHub.