Skip to content
This repository was archived by the owner on Feb 16, 2026. It is now read-only.

fix: io errors nested in hyper request errors not classified as retryable#295

Merged
quettabit merged 1 commit intomainfrom
qb/fix-unexp-eof
Feb 7, 2026
Merged

fix: io errors nested in hyper request errors not classified as retryable#295
quettabit merged 1 commit intomainfrom
qb/fix-unexp-eof

Conversation

@quettabit
Copy link
Member

No description provided.

@quettabit quettabit requested a review from a team as a code owner February 7, 2026 03:15
@greptile-apps
Copy link

greptile-apps bot commented Feb 7, 2026

Greptile Overview

Greptile Summary

  • Adjusts ClientError::from(reqwest::Error) to check for a nested std::io::Error before handling err.is_request()/hyper::Error cases, so certain IO errors (e.g., UnexpectedEof) can be classified explicitly.
  • This affects ApiError::is_retryable() via ClientError::is_retryable(), changing which transport failures trigger backoff retries in RequestBuilder::send().
  • Main impact area is request/streaming operations (append, read, session APIs) that rely on the retry loop for transient network failures.

Confidence Score: 3/5

  • This PR is likely safe to merge once retry classification semantics are confirmed for other transient io::ErrorKind cases.
  • The change is small and targeted, but it modifies error classification precedence in a way that can alter retry behavior for nested IO errors beyond UnexpectedEof; without tests in this environment, there’s moderate uncertainty about regressions in retryability for other transient network failures.
  • src/api.rs (ClientError::from(reqwest::Error) classification logic)

Important Files Changed

Filename Overview
src/api.rs Reordered reqwest::Error classification to inspect nested std::io::Error before hyper request errors; likely fixes UnexpectedEof retryability but may newly classify other transient io::ErrorKind values as non-retryable via ClientError::Others.

Sequence Diagram

sequenceDiagram
  participant User
  participant BasinClient
  participant RB as RequestBuilder
  participant Reqwest as reqwest::Client
  participant ErrMap as ClientError::from
  participant Retry as RetryBackoff

  User->>BasinClient: "read()/append()/..."
  BasinClient->>RB: "send()"
  RB->>Reqwest: "execute(request)"

  alt "Response"
    Reqwest-->>RB: "Ok(Response)"
    RB-->>User: "Ok or ApiError::Server"
  else "Transport error"
    Reqwest-->>RB: "Err(reqwest::Error)"
    RB->>ErrMap: "classify"
    alt "connect/timeout"
      ErrMap-->>RB: "Connect/Timeout"
    else "nested io::Error (new precedence)"
      ErrMap-->>RB: "map by io::ErrorKind"
    else "request + hyper::Error"
      ErrMap-->>RB: "ConnectionClosedEarly/RequestCanceled/Others"
    else "fallback"
      ErrMap-->>RB: "Others"
    end

    alt "retryable"
      RB->>Retry: "next()"
      Retry-->>RB: "Duration"
      RB->>Reqwest: "execute(retry)"
    else "not retrying"
      RB-->>User: "Err(ApiError)"
    end
  end
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@quettabit quettabit merged commit d6aabc0 into main Feb 7, 2026
6 checks passed
@quettabit quettabit deleted the qb/fix-unexp-eof branch February 7, 2026 03:25
@github-actions github-actions bot mentioned this pull request Feb 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant