`h2::Error` hides IO error
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 1.6k
- Forks
- 382
- Avg merge
- 20h 23m
- Merged PRs (30d)
- 9
Description
In uv, we want to retry streaming downloads on connection reset errors. These errors are common e.g. in GitHub Actions when downloading e.g. a 20MB file.
Our goal is to have a streaming download-and-unpack. We have a loop in which we try the streaming download-and-unpack, and if it fails, inspect the error chain on whether it looks like a retryable network error (https://github.com/astral-sh/uv/blob/22f80ca00d3f5af7d087154e998c886bbea8cee1/crates/uv-python/src/downloads.rs#L945-L993). This is easy for status code errors, where we get a reqwest::Error at the top of the error chain, but during the stream, the error may be nested in several layer of other crates involved in the unpacking, see the example error below.
We want to specifically retry io::ErrorKind::ConnectionReset. But when trying err.downcast_ref::<io::Error>() we don't get anything, as the h2 error wraps the IO error, which is not apparent from the debug output.
Tar(
TarError {
desc: "failed to unpack `/home/konsti/.local/share/uv/python/.temp/.tmpBHaUXj/python/bin/python3.12`",
io: Custom {
kind: Other,
error: TarError {
desc: "failed to unpack `python/bin/python3.12` into `/home/konsti/.local/share/uv/python/.temp/.tmpBHaUXj/python/bin/python3.12`",
io: Custom {
kind: Other,
error: reqwest::Error {
kind: Decode,
source: reqwest::Error {
kind: Body,
source: Error {
inner: ErrorImpl {
kind: Body,
cause: Some(
Error {
kind: Io(
Kind(
ConnectionReset,
),
),
},
),
},
},
},
},
},
},
},
},
)
I'm also interested in ways to make our transient network error detection (https://github.com/astral-sh/uv/blob/f88aaa8740824b03be36c7ff106a139151452165/crates/uv-client/src/base_client.rs#L983-L1067) more reliable in general, without going through reqwest's error chain.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the error-chain handling described in crates/uv-python/src/downloads.rs lines 945-993 and crates/uv-client/src/base_client.rs lines 983-1067, then trace how the h2 error hides the nested IO error. Done means callers can reliably identify io::ErrorKind::ConnectionReset in streaming download failures without depending on reqwest-specific error inspection.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 28/100