Hmbown/CodeWhale · error
SSE stream idle timeout after {}s — no data received (bytes_
Error message
SSE stream idle timeout after {}s — no data received (bytes_received={}, stream_age_ms={}, ms_since_last_chunk={}) What it means
On the Antigravity cloud-code route, the tokio timeout around the next chunk elapsed: no bytes arrived within the idle window. The message is built by the shared `stream_entry::idle_timeout_message` and reports idle seconds, bytes received, stream age, and time since the last chunk, distinguishing never-started from stalled-mid-stream.
Source
Thrown at crates/tui/src/client/cloud_code.rs:184
let byte_stream = response.bytes_stream();
let stream = async_stream::stream! {
let mut buffer: Vec<u8> = Vec::new();
let stream_start = std::time::Instant::now();
let mut last_chunk_at = std::time::Instant::now();
let mut bytes_received: usize = 0;
let mut started = false;
tokio::pin!(byte_stream);
loop {
let chunk = match tokio::time::timeout(stream_idle_timeout, byte_stream.next()).await {
Ok(Some(Ok(chunk))) => chunk,
Ok(Some(Err(e))) => {
yield Err(anyhow::anyhow!("Stream read error: {e}"));
return;
}
Ok(None) => break,
Err(_) => {
yield Err(anyhow::anyhow!(stream_entry::idle_timeout_message(
stream_idle_timeout,
bytes_received,
stream_start.elapsed(),
last_chunk_at.elapsed(),
)));
return;
}
};
bytes_received += chunk.len();
last_chunk_at = std::time::Instant::now();
buffer.extend_from_slice(&chunk);
loop {
let line = match super::take_sse_line(&mut buffer) {
Ok(Some(line)) => line,
Ok(None) => break,
Err(err) => {
yield Err(anyhow::anyhow!("{err}"));View on GitHub (pinned to 8880682c63)
Solutions
- Retry — silent stalls are usually transient
- Raise the stream idle timeout above the route's expected time-to-first-event
- If bytes_received=0 always, verify the endpoint/auth — the server never starts
- Bypass intermediaries that idle-kill quiet connections
Defensive patterns
Strategy: retry
Type guard
fn is_idle_timeout(err: &anyhow::Error) -> bool {
err.to_string().contains("idle timeout after")
} Try / catch
match stream.next().await {
Some(Err(e)) if is_idle_timeout(&e) => {
backoff().await;
stream = client.reopen_cloud_code_stream(request).await?;
}
Some(Err(e)) => return Err(e),
other => { /* forward */ }
} Prevention
- Size the stream idle timeout for the cloud-code route's long silent planning phases
- Use the embedded diagnostics to distinguish never-started (bytes_received=0) from stalled streams
- Avoid idle-killing proxies on long agentic sessions
When it happens
Trigger: Long server-side thinking phase before the first cloud-code event; stalled proxy; provider hang after 200 OK; idle timeout smaller than the route's time-to-first-byte.
Common situations: Heavy agentic tasks with long silent planning phases; mobile/high-latency networks; proxies idle-killing quiet SSE connections.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Stream read error: {e}
- Antigravity cloud-code is stream-only; blocking create_messa
- SSE stream idle timeout after {}s — no data received (bytes_
- Antigravity cloud-code stream ended without a text part
- SSE stream idle timeout after {}s — no data received (bytes_
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/4919144a674b6859.
Report an issue: GitHub.