NousResearch/hermes-agent · error · TimeoutError
Non-streaming API call timed out after {int(time.time() - ca
Error message
Non-streaming API call timed out after {int(time.time() - call_start)}s with no response (threshold: {int(stale_timeout)}s) What it means
The non-streaming API call raised a transport exception and the watchdog had already flagged the request stale; Hermes deliberately converts this into a retryable TimeoutError (never InterruptedError, which would read as 'user wants to stop') so the outer retry loop reconnects on a fresh pool. Elapsed time and threshold are included for diagnosis.
Source
Thrown at agent/chat_completion_helpers.py:814
# Only a clean return may report the reuse reason (request_complete):
# after an error or interrupt the wire client is really closed so the
# retry builds a fresh pool (see _REQUEST_CLIENT_REUSE_REASONS).
succeeded = False
try:
response = _dispatch_nonstreaming_api_request(
agent, api_kwargs, make_client=_make_client
)
except Exception:
if getattr(agent, "_interrupt_requested", False):
raise InterruptedError("Agent interrupted during API call") from None
with request_client_lock:
was_stale = request_state["stale"]
if was_stale:
# The transport error is the expected consequence of our own
# abort. Raise a retryable TimeoutError (never InterruptedError,
# which the outer loop treats as "the user wants to stop") so the
# retry loop reconnects on a fresh pool.
raise TimeoutError(
f"Non-streaming API call timed out after "
f"{int(time.time() - call_start)}s with no response "
f"(threshold: {int(stale_timeout)}s)"
) from None
raise
else:
if getattr(agent, "_interrupt_requested", False):
raise InterruptedError("Agent interrupted during API call")
# Close the race window against a timer firing between response
# arrival and this unwind: marking ``done`` under the lock makes any
# later timer callback a no-op, so the reset below cannot be
# overwritten by a stray bump after a successful call. A timer that
# already won the lock left ``stale`` set — the request still
# completed, so return the response (the streak reset undoes the
# bump; the poisoned client is discarded by the finally).
with request_client_lock:
request_state["done"] = True
_reset_stale_streak(agent)View on GitHub (pinned to c896c09c42)
Solutions
- Retry — this error is intentionally retryable and the loop uses a fresh connection pool.
- If recurrent, lower prompt size or switch to a streaming call (time-to-first-token arrives earlier).
- Increase the stale timeout for legitimately slow setups (very large contexts, local models on weak hardware).
- Check provider status / network path if every call times out.
Defensive patterns
Strategy: retry
Validate before calling
if estimated_time_to_first_byte(provider, prompt_tokens) > stale_timeout:
trim_prompt_or_switch_to_streaming() Try / catch
attempts = 0
while attempts < 3:
try:
return non_streaming_call(...)
except TimeoutError as e:
if "no response" in str(e) and "threshold" in str(e):
attempts += 1
backoff(attempts)
continue
raise Prevention
- Use streaming for large prompts — tokens arrive before the stale threshold.
- Tune stale timeouts for slow local models instead of relying on retries.
- Treat recurring stale timeouts as an endpoint health signal, not noise.
When it happens
Trigger: A non-streaming completion received no response within stale_timeout; the abort timer fired, killed the request, the transport then raised, and the stale flag was set at agent/chat_completion_helpers.py:814.
Common situations: Slow provider exceeding the stale threshold; oversized prompt causing long time-to-first-byte on non-streaming responses; network black-holing; provider under heavy load.
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 before request dispatch (th
- Could not refresh the remote gateway WebSocket ticket.
- gateway not connected: ${method}
- Codex auxiliary Responses stream exceeded {float(total_timeo
- Auxiliary streamed call timed out after {self._total_ceiling
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/94309853ae0ba06e.
Report an issue: GitHub.