seanmonstar/reqwest · error · reqwest::Error
request or response body error
Error message
request or response body error
What it means
The `Kind::Body` error from `error::body(...)` (error.rs:348-350). It fires when reading or writing the streaming body fails — most commonly a body read/write timeout (body.rs:309 and body.rs:352 wrap `TimedOut`), or an h3 pool stream body error (pool.rs:343/351).
Source
Thrown at src/error.rs:349
Request,
Redirect,
#[cfg(not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))]
Status(StatusCode, Option<hyper::ext::ReasonPhrase>),
#[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
Status(StatusCode),
Body,
Decode,
Upgrade,
}
// constructors
pub(crate) fn builder<E: Into<BoxError>>(e: E) -> Error {
Error::new(Kind::Builder, Some(e))
}
pub(crate) fn body<E: Into<BoxError>>(e: E) -> Error {
Error::new(Kind::Body, Some(e))
}
pub(crate) fn decode<E: Into<BoxError>>(e: E) -> Error {
Error::new(Kind::Decode, Some(e))
}
pub(crate) fn request<E: Into<BoxError>>(e: E) -> Error {
Error::new(Kind::Request, Some(e))
}
pub(crate) fn dns<E: Into<BoxError>>(e: E) -> BoxError {
Box::new(DnsError { inner: e.into() })
}
pub(crate) fn redirect<E: Into<BoxError>>(e: E, url: Url) -> Error {
Error::new(Kind::Redirect, Some(e)).with_url(url)
}
View on GitHub (pinned to 17e9bcb51c)
Solutions
- Raise or remove the timeout for large transfers: `.timeout(Duration::from_secs(300))` or per-request `.request_timeout`.
- Use `error.is_timeout()` to distinguish a body timeout from a genuine I/O failure and retry only timeouts.
- Stream the body in chunks instead of buffering, so progress resets the timeout window if using a per-byte deadline.
- Inspect `e.source()` for the underlying hyper/h3/io error to confirm it's not a real protocol failure.
Example fix
// before let client = Client::builder().timeout(Duration::from_secs(5)).build()?; let bytes = client.get(url).send().await?.bytes().await?; // body timeout on big payload // after let client = Client::builder().timeout(Duration::from_secs(120)).build()?; let bytes = client.get(url).send().await?.bytes().await?;
Defensive patterns
Strategy: retry
Validate before calling
// No body-size pre-check, but size the timeout to the payload. let timeout = estimate_timeout(payload_len, link_bps); let client = Client::builder().timeout(timeout).build()?;
Type guard
fn is_body_or_body_timeout(e: &reqwest::Error) -> bool { e.is_body() || (e.is_timeout() && e.is_body()) }
Try / catch
match resp.bytes().await {
Ok(b) => Ok(b),
Err(e) if e.is_timeout() => retry().await,
Err(e) if e.is_body() => Err(anyhow!("body error: {}", e.source().map(|s| s.to_string()).unwrap_or_default())),
Err(e) => Err(e.into()),
} Prevention
- Set timeouts proportional to expected payload size and link speed.
- Stream large bodies in chunks to surface progress.
- Distinguish is_timeout() from genuine body failures before retrying.
When it happens
Trigger: A request body upload or response body download exceeding the client/per-request `.timeout()`; the peer resets the stream mid-body; the response stream yields an h3/hyper body error during `.bytes()`/`.text()`/streaming.
Common situations: Large file upload over a slow link with a tight `.timeout(Duration::from_secs(5))`; streaming a huge JSON response that stalls; slow mobile network where the body never finishes in time; server closes the connection while you're still reading.
Related errors
AI-assisted analysis of seanmonstar/reqwest@17e9bcb51c (2026-08-06).
Data as JSON: /data/errors/fbfad586e94b6d42.json.
Report an issue: GitHub.