Skip to content

Commit

Permalink
Catch retries with wrapped reqwest errors (#9253)
Browse files Browse the repository at this point in the history
## Summary

It turns out that `WrappedReqwestError` skips the `reqwest::Error`
itself in order to hack the display. This PR adds it to the list of
variants we check when retrying transient errors.

Closes #9246.


## Test Plan

Patched `reqwest` locally to return an error in `bytes()`. Verified that
it was _not_ caught prior to this PR, but was caught afterwards.
  • Loading branch information
charliermarsh authored Nov 19, 2024
1 parent 8e0389e commit 9fb7f81
Showing 1 changed file with 16 additions and 1 deletion.
17 changes: 16 additions & 1 deletion crates/uv-client/src/base_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use uv_warnings::warn_user_once;
use crate::linehaul::LineHaul;
use crate::middleware::OfflineMiddleware;
use crate::tls::read_identity;
use crate::Connectivity;
use crate::{Connectivity, WrappedReqwestError};

pub const DEFAULT_RETRIES: u32 = 3;

Expand Down Expand Up @@ -461,6 +461,20 @@ impl RetryableStrategy for UvRetryableStrategy {
///
/// These cases should be safe to retry with [`Retryable::Transient`].
pub(crate) fn is_extended_transient_error(err: &dyn Error) -> bool {
// First, look for `WrappedReqwestError`, which wraps `reqwest::Error` but doesn't always
// include it in the source.
if let Some(err) = find_source::<WrappedReqwestError>(&err) {
if let Some(io) = find_source::<std::io::Error>(&err) {
if io.kind() == std::io::ErrorKind::ConnectionReset
|| io.kind() == std::io::ErrorKind::UnexpectedEof
{
return true;
}
}
}

// Next, look for `reqwest_middleware::Error`, which wraps `reqwest::Error`, but also includes
// errors from the middleware stack.
if let Some(err) = find_source::<reqwest_middleware::Error>(&err) {
if let Some(io) = find_source::<std::io::Error>(&err) {
if io.kind() == std::io::ErrorKind::ConnectionReset
Expand All @@ -471,6 +485,7 @@ pub(crate) fn is_extended_transient_error(err: &dyn Error) -> bool {
}
}

// Finally, look for `reqwest::Error`, which is the most common error type.
if let Some(err) = find_source::<reqwest::Error>(&err) {
if let Some(io) = find_source::<std::io::Error>(&err) {
if io.kind() == std::io::ErrorKind::ConnectionReset
Expand Down

0 comments on commit 9fb7f81

Please sign in to comment.