Hmbown/CodeWhale · error · anyhow::Error
SSE stream idle timeout after
Error message
SSE stream idle timeout after {idle_secs}s — no data received (bytes_received={bytes}, stream_age_ms={age}, ms_since_last_chunk={since}) What it means
This error is raised in the Anthropic streaming client when no bytes arrive from the Messages API SSE stream for longer than the configured idle timeout (stream_idle_timeout). The tokio::time::timeout wrapping byte_stream.next() fires with Err(_), and the stream yields this diagnostic message with bytes_received, stream age, and time since the last chunk to aid debugging. It aborts the stream immediately rather than letting a stalled connection hang the turn.
Solutions
- Increase stream_idle_timeout in the client configuration if long pauses between chunks are expected for your model.
- Check Anthropic status / retry the request — a mid-stream stall is usually transient.
- Verify no proxy or VPN is buffering or dropping SSE connections; try a direct connection.
- Enable network-level keepalives or use a provider/proxy that sends SSE comments as heartbeats.
Example fix
// before: default timeout too short for extended thinking let client = AnthropicClient::new().with_stream_idle_timeout(Duration::from_secs(30)); // after let client = AnthropicClient::new().with_stream_idle_timeout(Duration::from_secs(300));
Defensive patterns
Strategy: retry
Validate before calling
// before the call: ensure timeout is sane assert!(idle_timeout >= Duration::from_secs(30), "idle timeout too small for LLM streams");
Try / catch
// stream errors are anyhow::Error items on the stream
while let Some(item) = stream.next().await {
match item {
Ok(ev) => handle(ev),
Err(e) if e.to_string().contains("idle timeout") => {
warn!("stream stalled: {e}");
retry_with_backoff();
}
Err(e) => return Err(e),
}
} Prevention
- Set stream_idle_timeout generously for reasoning models with long quiet periods
- Use proxies that forward SSE immediately (disable buffering)
- Monitor provider status pages and add circuit-breaking
- Enable TCP/application-level keepalives
When it happens
Trigger: Any Anthropic streaming request where the HTTP connection stays open but delivers zero bytes for stream_idle_timeout: provider outage mid-stream, network path stalls (VPN, proxy keepalive drop), a hung model, or a proxy that accepts the request but never relays the response body.
Common situations: Corporate proxies buffering SSE indefinitely; long 'thinking' pauses exceeding the configured timeout; Anthropic API partial outages; mobile/unstable networks dropping the connection silently without TCP FIN.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- SSE stream idle timeout after
- SSE stream idle timeout after
- SSE stream idle timeout after
- SSE stream idle timeout after
- SSE stream idle timeout after
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/1732c13847a5d2d8.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/client/anthropic.rs:334
let mut bytes_received: usize = 0;
let mut ended = false;
tokio::pin!(byte_stream);
loop {
if !ended {
match tokio::time::timeout(stream_idle_timeout, byte_stream.next()).await {
Ok(Some(Ok(chunk))) => {
bytes_received += chunk.len();
last_chunk_at = std::time::Instant::now();
buffer.extend_from_slice(&chunk);
}
Ok(Some(Err(e))) => {
yield Err(anyhow::anyhow!("Stream read error: {e}"));
return;
}
Ok(None) => ended = true,
Err(_) => {
yield Err(anyhow::anyhow!(super::stream_entry::idle_timeout_message(
stream_idle_timeout,
bytes_received,
stream_start.elapsed(),
last_chunk_at.elapsed(),
)));
return;
}
}
}
loop {
let line = match next_sse_line(&mut buffer, ended) {
Ok(Some(line)) => line,
Ok(None) => break,
Err(err) => {
yield Err(anyhow::anyhow!("{err}"));
return;
}View on GitHub (pinned to 433685b202)