t8y2/dbx · critical · RuntimeError

agent exited before ready

Error message

agent exited before ready

What it means

During agent startup, _wait_ready reads the agent's stdout waiting for a JSON line with ready=true. If the agent process exits before sending that line, it raises RuntimeError('agent exited before ready') wrapped with _failure context. This distinguishes a crash during startup from a hang.

Source

Thrown at agents/drivers/cassandra-go/bench/agent_compare.py:49

            bufsize=1,
        )
        self.request_id = 0
        self.stderr_lines: list[str] = []
        threading.Thread(target=self._drain_stderr, daemon=True).start()
        self._wait_ready()

    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 _wait_ready(self) -> None:
        assert self.process.stdout is not None
        deadline = time.monotonic() + env_float("BENCH_READY_TIMEOUT", 30.0)
        while time.monotonic() < deadline:
            line = self.process.stdout.readline()
            if line == "" and self.process.poll() is not None:
                raise RuntimeError(self._failure("agent exited before ready"))
            try:
                if json.loads(line).get("ready") is True:
                    return
            except (json.JSONDecodeError, AttributeError):
                continue
        raise TimeoutError(self._failure("timed out waiting for agent readiness"))

    def call(self, method: str, params: dict | None = None) -> dict:
        self.request_id += 1
        request = {
            "jsonrpc": "2.0",
            "id": self.request_id,
            "method": method,
            "params": params or {},
        }
        assert self.process.stdin is not None
        assert self.process.stdout is not None
        self.process.stdin.write(json.dumps(request, separators=(",", ":")) + "\n")

View on GitHub (pinned to c0390bff16)

Solutions

  1. Run the agent command manually to see its actual startup error
  2. Verify the candidate binary path and that it is executable for this platform
  3. Check agent logs/stderr for panics, missing config, or port conflicts
  4. Confirm the agent version emits a JSON line with "ready": true on stdout

Example fix

// before (agent missing)
CANDIDATE_BIN=./argo-agent-missing python agent_compare.py
// after
CANDIDATE_BIN=./target/release/argo-agent python agent_compare.py
Defensive patterns

Strategy: try-catch

Validate before calling

# before constructing the agent, verify the binary
bin_path = os.getenv("CANDIDATE_BIN", "")
if not bin_path or not os.path.isfile(bin_path) or not os.access(bin_path, os.X_OK):
    raise SystemExit(f"candidate binary missing or not executable: {bin_path}")

Try / catch

try:
    agent = AgentProcess(cmd)
except RuntimeError as exc:
    if "agent exited before ready" in str(exc):
        print("agent stderr:", agentStderrTail())  # capture captured stderr for diagnosis
        sys.exit(2)
    raise

Prevention

When it happens

Trigger: Launching the agent subprocess in __init__ when the binary path is wrong, the agent panics on bad flags/config, or it exits immediately due to missing files or port conflicts — its stdout hits EOF before a ready message.

Common situations: Pointing BENCH at a non-executable or wrong-architecture binary; agent fails on database connection at boot; agent built from an older version that never emits a ready line.

Related errors


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