NousResearch/hermes-agent · error · TimeoutError
codex app-server method {method!r} timed out after {timeout}
Error message
codex app-server method {method!r} timed out after {timeout}s What it means
TimeoutError from CodexAppServerClient.request() (agent/transports/codex_app_server.py:231). Each request registers a per-id response queue; if the codex app-server subprocess does not deliver a response for that id within `timeout` seconds, queue.get raises Empty, the pending entry is cleaned up, and this TimeoutError is raised naming the method and timeout.
Source
Thrown at agent/transports/codex_app_server.py:231
def request(
self,
method: str,
params: Optional[dict] = None,
timeout: float = 30.0,
) -> dict:
"""Send a JSON-RPC request and block on the response. Returns `result`,
raises CodexAppServerError on `error`."""
rid = self._take_id()
q: queue.Queue = queue.Queue(maxsize=1)
with self._pending_lock:
self._pending[rid] = _Pending(queue=q, method=method)
self._send({"id": rid, "method": method, "params": params or {}})
try:
msg = q.get(timeout=timeout)
except queue.Empty:
with self._pending_lock:
self._pending.pop(rid, None)
raise TimeoutError(
f"codex app-server method {method!r} timed out after {timeout}s"
)
if "error" in msg:
err = msg["error"]
raise CodexAppServerError(
code=err.get("code", -1),
message=err.get("message", ""),
data=err.get("data"),
)
return msg.get("result", {})
def notify(self, method: str, params: Optional[dict] = None) -> None:
"""Send a JSON-RPC notification (no id, no response expected)."""
self._send({"method": method, "params": params or {}})
def respond(self, request_id: Any, result: dict) -> None:
"""Reply to a server-initiated request (e.g. approval prompts)."""
self._send({"id": request_id, "result": result})View on GitHub (pinned to c896c09c42)
Solutions
- Pass a larger timeout for methods known to be slow: client.request('turn/start', params, timeout=120.0).
- Check the subprocess is alive and the reader thread is running (a dead process usually also produces stdin-closed errors from _send).
- If the process died, tear down the client and start a new one rather than retrying on the same connection.
- Retry idempotent methods once after a transient timeout, but never blind-retry initialize() on the same client (see the 'already initialized' error).
Example fix
# before
result = client.request("thread/start", params) # default 10s
# after
result = client.request("thread/start", params, timeout=60.0) Defensive patterns
Strategy: retry
Validate before calling
import subprocess
def codex_alive(proc: subprocess.Popen) -> bool:
return proc.poll() is None and proc.stdin is not None and not proc.stdin.closed Try / catch
try:
result = client.request(method, params, timeout=timeout)
except TimeoutError:
if client._proc.poll() is not None:
raise # child died; retrying is pointless
result = client.request(method, params, timeout=timeout * 2) # one bounded retry Prevention
- Pass explicit, per-method timeouts sized to the operation (initialize default is 10s).
- Watch the reader thread / process liveness so a dead server is detected before a request times out.
- Only retry idempotent methods; never blind-retry the initialize handshake on the same client.
When it happens
Trigger: request(method, params, timeout=N) where the codex app-server is hung, still starting up, busy on a long operation (default timeout is 10.0s from initialize), or has died without the caller noticing; also a response routed to a dead reader thread never reaches the queue.
Common situations: Cold start of the codex binary exceeding the default 10s; a long-running turn/step method invoked with the default timeout; the app-server process crashed earlier and only the next request surfaces it; system under heavy load.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- codex app-server stdin not available
- Codex auxiliary Responses stream exceeded {float(total_timeo
- already initialized
- codex app-server error {code}: {message}
- codex app-server client is closed
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/d2eb519527ae2996.
Report an issue: GitHub.