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

The Responses API stream received no data at all from the server for longer than the configured idle timeout (`stream_idle_timeout`). The `select!` branch on the read future timed out, and the handler yields a diagnostic message (built by `idle_timeout_message`) that includes bytes received, stream age, and time since the last chunk, then aborts. This prevents hanging forever on a stalled connection.

Solutions

  1. Retry the request; stalls are often transient provider-side load
  2. Increase the stream idle timeout configuration if the model legitimately has long silent periods
  3. Check provider status / self-hosted server logs for the stall cause
  4. Confirm no proxy is buffering the SSE response (buffering proxies suppress chunk delivery)
Defensive patterns

Strategy: retry

Try / catch

match result {
    Err(e) if e.to_string().contains("SSE stream idle timeout") => {
        let diag = e.to_string(); // parse bytes_received/ms_since_last_chunk for diagnosis
        retry_with_backoff();
    }
    other => other,
}

Prevention

When it happens

Trigger: The server accepts the request but sends no bytes within `stream_idle_timeout` seconds; the connection stalls mid-stream after some chunks (diagnostics show bytes_received > 0); a hung upstream behind a proxy that keeps the socket open but forwards nothing.

Common situations: Provider outages where the endpoint accepts connections but never streams; overloaded self-hosted inference servers queuing requests; misconfigured keepalive behind load balancers; extremely long time-to-first-token on large prompts.

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.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/8daac956073b363a. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/client/responses.rs:282

            let mut bytes_received: usize = 0;

            tokio::pin!(byte_stream);

            while !done {
                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;
                        }
                    }
                }

                // Process complete SSE lines, and the unterminated tail at stream end.
                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)