wasmerio/wasmer · error
Timeout while downloading response body
Error message
Timeout while downloading response body
What it means
The WASIX reqwest-based HTTP host implementation streams the response body in chunks under a per-chunk timeout in `request`. If the timeout fires before any chunk has been downloaded (chunk_count == 0), it aborts with 'Timeout while downloading response body'. If some chunks were already received, it resets the timeout and keeps going — so this specifically means nothing at all arrived within the window.
Source
Thrown at lib/wasix/src/http/reqwest.rs:121
res = stream.try_next() => {
match res {
Ok(Some(chunk)) => {
buf.extend_from_slice(&chunk);
chunk_count += 1;
}
Ok(None) => {
break 'OUTER;
}
Err(e) => {
return Err(e.into());
}
}
}
_ = &mut timeout => {
if chunk_count == 0 {
tracing::warn!(timeout= "timeout while downloading response body");
return Err(anyhow::anyhow!("Timeout while downloading response body"));
} else {
tracing::debug!(downloaded_body_size_bytes=%buf.len(), "download progress");
// Timeout, but chunks were downloaded, so
// just continue with a fresh timeout.
continue 'OUTER;
}
}
}
}
}
buf
} else {
response.bytes().await?.to_vec()
};
#[cfg(feature = "js")]
let data = response.bytes().await?.to_vec();
View on GitHub (pinned to 8c4b9ee9d3)
Solutions
- Retry the request — transient network stalls are the most common cause and succeed on retry.
- Check the remote server's health/logs: it likely accepted the request but never wrote a body.
- Verify network connectivity and that no firewall/NAT is silently dropping established connections.
- If behind a proxy, confirm the proxy streams chunked responses instead of buffering.
- Increase the body-download timeout in the WASIX HTTP configuration if the server is legitimately slow.
Example fix
// before: single attempt
let resp = http.request(req).await?;
// after: retry on body-download timeout
let resp = match http.request(req.clone()).await {
Ok(r) => r,
Err(e) if e.to_string().contains("Timeout while downloading response body") => {
tokio::time::sleep(Duration::from_secs(1)).await;
http.request(req).await?
}
Err(e) => return Err(e.into()),
}; Defensive patterns
Strategy: retry
Validate before calling
// preflight: probe the endpoint with a short timeout before the real call
async fn reachable(url: &str) -> bool {
reqwest::Client::new()
.head(url)
.timeout(Duration::from_secs(5))
.send()
.await
.map(|r| r.status().is_success())
.unwrap_or(false)
} Try / catch
async fn request_with_retry(http: &Http, req: Request) -> Result<Response> {
const MAX: usize = 3;
for attempt in 1..=MAX {
match http.request(req.clone()).await {
Ok(r) => return Ok(r),
Err(e) if e.to_string().contains("Timeout while downloading response body") && attempt < MAX => {
tokio::time::sleep(Duration::from_millis(500 * attempt as u64)).await;
}
Err(e) => return Err(e.into()),
}
}
unreachable!()
} Prevention
- Wrap WASIX HTTP calls in retry-with-backoff for transient stalls
- Set explicit timeouts on the guest-side HTTP client
- Monitor backend services for hung requests (slow endpoints trigger this)
- Verify firewalls/NAT don't silently drop idle established connections
When it happens
Trigger: WASM module issues an HTTP request whose response body never starts arriving within the timeout: server hangs after sending headers, network stalls, or a very slow/hung upstream behind a proxy.
Common situations: Backend service in the WASM app hangs (deadlocked DB query); firewall drops the connection silently after headers; huge slow upload on a poor mobile connection; proxy holding the response without streaming it.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- unsupported content-encoding: {other}
- Cannot load reference type
- Could not apply request header: '{name}': '{value}'
- unimplemented operator {operator:?}
- global #{} is a constant
AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01).
Data as JSON: /api/errors/ba47cccf1281a22a.
Report an issue: GitHub.