NousResearch/hermes-agent · error · TimeoutError
Non-streaming API call timed out before request dispatch (th
Error message
Non-streaming API call timed out before request dispatch (threshold: {int(stale_timeout)}s) What it means
On the non-streaming API path, a stale watchdog detected that the call exceeded the stale threshold before the request was even dispatched (client registration/creation stalled, e.g. a wedged connection pool). The client was aborted via _abort_request_openai_client and the code raises TimeoutError pre-dispatch so the retry loop can rebuild on a fresh pool instead of stacking onto the dead one.
Source
Thrown at agent/chat_completion_helpers.py:744
# (registration race): the abort found no sockets to kill, so
# handing this client to dispatch would open a brand-new
# socket after the only watchdog already fired. Abort it here
# and fail the call instead. (The residual window — timer
# firing between this registration and httpx opening its
# socket — is accepted: it is ms-scale against a >=90s budget
# and self-bounds at the OS connect-retry cap.)
stale_before_dispatch = True
try:
agent._abort_request_openai_client(
client, reason="stale_call_kill"
)
except Exception:
logger.debug(
"Inline abort after late client registration failed",
exc_info=True,
)
if stale_before_dispatch:
raise TimeoutError(
"Non-streaming API call timed out before request dispatch "
f"(threshold: {int(stale_timeout)}s)"
)
agent._active_request_abort = _abort_active_request
return client
def _activity_heartbeat() -> None:
# Do not put the API call itself on another worker thread — that is
# the nested-pool deadlock this path exists to avoid (#60203). This
# ticker only refreshes the activity clock.
while not activity_hb_stop.wait(_DIRECT_API_ACTIVITY_HEARTBEAT_SECONDS):
try:
agent._touch_activity("waiting for non-streaming API response")
except Exception:
pass
activity_hb = threading.Thread(
target=_activity_heartbeat,View on GitHub (pinned to c896c09c42)
Solutions
- Let the retry loop run — the pre-dispatch abort is designed to reconnect on a fresh pool; persistent recurrence means the endpoint is down.
- Verify the base_url endpoint health (curl -m 10).
- Restart or switch the model server/provider.
- For local endpoints, confirm the server process is alive and not out of file descriptors.
Defensive patterns
Strategy: retry
Validate before calling
import socket, urllib.parse
def endpoint_dispatchable(base_url, timeout=10) -> bool:
u = urllib.parse.urlparse(base_url)
try:
with socket.create_connection((u.hostname, u.port or (443 if u.scheme == "https" else 80)), timeout=timeout):
return True
except OSError:
return False Try / catch
for attempt in range(max_retries):
try:
return non_streaming_call(...)
except TimeoutError as e:
if "before request dispatch" in str(e):
continue # fresh pool on next iteration by design
raise Prevention
- Health-check endpoints before long runs.
- Keep connection pools bounded so one wedged pool cannot stall dispatch.
- For local model servers, monitor process liveness and file-descriptor exhaustion.
When it happens
Trigger: The make_client/registration path itself blocks past the stale_timeout — connect-retry caps, exhausted connection pool, or DNS stall — before any bytes are sent (agent/chat_completion_helpers.py:744).
Common situations: Provider endpoint half-down (TCP accepts, TLS hangs); saturated local connection pool from earlier stale calls; DNS issues; localhost model server that died with sockets lingering.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Non-streaming API call timed out after {int(time.time() - ca
- Codex auxiliary Responses stream exceeded {float(total_timeo
- Auxiliary streamed call timed out after {self._total_ceiling
- Provider has been unresponsive (no response received) for {_
- iron-proxy did not bind {probe_host}:{tunnel_port} within {_
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/e7e808e99a4cc823.
Report an issue: GitHub.