Skip to content

Expose the proxy's classification of retryable errors - #155

Merged
cgwalters merged 1 commit into
bootc-dev:mainfrom
cgwalters-forge:bot/proxy-retryable-errors
Sep 30, 2026
Merged

cgwalters merged 1 commit into
bootc-dev:mainfrom
cgwalters-forge:bot/proxy-retryable-errors

Conversation

@cgwalters-bot

Copy link
Copy Markdown
Contributor

Since protocol 0.2.8 (skopeo 1.19), the proxy sets error_code: "retryable" on failed replies when containers/common's IsErrorRetryable() considers the error transient: network errors, HTTP 502-504, and registry error codes like TOOMANYREQUESTS. That's the same check podman uses to decide whether to retry a pull. We've been dropping that field, so a client that wants to retry can only match on the Go error text. composefs-rs wants to retry pulls (composefs/composefs-rs#348), and bootc would benefit too.

This adds Error::is_retryable(), backed by a new RetryableRequestFailure variant. It also covers the GetRawBlob error-pipe classification that was already there, and FinishPipe replies, so a GetBlob transfer that fails part way gets classified too. Error is #[non_exhaustive], so adding the variant isn't a semver break. With older proxies that don't send an error code, nothing is retryable, and behavior stays as before.

One behavior change for callers: code that matches RequestInitiationFailure to catch every failed reply will now miss the transient ones, which arrive as RetryableRequestFailure. That should go in the release notes. This is the typed error that the TODO in bootc's is_retryable_pull_error() (crates/lib/src/deploy.rs) asks for (bootc-dev/bootc#2466). Once this is released, bootc can call Error::is_retryable() there and also retry OpenImage failures.

Plan: land this and release it as 0.11.1. composefs-rs then replaces its temporary git [patch] with a version bump (cgwalters-forge/composefs-rs#1).

Tested on a 16-core devspace (RHEL 10, skopeo 1.22.2): cargo fmt --check, cargo test --all-features (includes a new test against real skopeo: connection refused on docker:// is retryable, a missing oci: dir isn't), and cargo clippy with no new warnings. The same tests also ran in quay.io/almalinuxorg/almalinux-bootc:10.0 (skopeo 1.18, where the skopeo test is skipped). cargo semver-checks (in Fedora, rustc 1.98) reports no semver update required.

Related: composefs/composefs-rs#348

The Signed-off-by: Colin Walters <walters@verbum.org> on these commits was added on cgwalters's approval of the review draft: cgwalters-forge#2 (review)

Generated-by: https://github.com/cgwalters/#llms

Since protocol 0.2.8 (skopeo 1.19), every failed reply carries an
error_code, which is "retryable" when containers/common's
IsErrorRetryable() considers the error transient: network failures,
HTTP 502-504 and registry error codes such as TOOMANYREQUESTS. That is
the same heuristic podman uses to decide whether to retry a pull. We
dropped it, so clients that want to retry (composefs-rs, bootc) could
only match on the Go error text.

Return such failures as the new RetryableRequestFailure variant, and
add Error::is_retryable(), which also covers the classification
GetRawBlob already reported on its error pipe. This covers FinishPipe
too, so GetBlob transfers that fail part way are classified as well.
Error is non_exhaustive, so the new variant is not a breaking change.

Generated-by: AI
Signed-off-by: Colin Walters <walters@verbum.org>
@cgwalters

Copy link
Copy Markdown
Collaborator

That said, we should be careful to be sure this wouldn't break either of those

@cgwalters
cgwalters merged commit 1e3e1b4 into bootc-dev:main Sep 30, 2026
6 checks passed
@cgwalters-bot

Copy link
Copy Markdown
Contributor Author

@cgwalters Checked: neither breaks. With [patch.crates-io] pointing at main (1e3e1b4), bootc (d296202) passes cargo check --workspace --all-targets and cargo test -p ostree-ext -p bootc-lib --lib (60 + 278 passed), and composefs-rs (32fb668) passes cargo check --workspace --all-targets and cargo test -p composefs-oci -p composefs-ctl (168 + 9 + 1 passed). Neither consumer matches on RequestInitiationFailure outside a bootc unit test that only constructs one, and the Display text is unchanged. cargo semver-checks --baseline-rev v0.11.0 reports no semver update required. All of this ran on a 16-core RHEL 10 devspace.

composefs/composefs-rs#407 does need a 0.11.1 release. Its nightly job fails in cargo package verification, where the git [patch] doesn't apply and crates.io 0.11.0 has no Error::is_retryable.

Generated-by: https://github.com/cgwalters/#llms

cgwalters-bot added a commit to cgwalters-forge/containers-image-proxy-rs that referenced this pull request Oct 2, 2026
Publish Error::is_retryable() (bootc-dev#155) so that callers such as
composefs-rs can retry transient registry errors without depending on a
git revision. The change only adds a variant to the #[non_exhaustive]
Error enum and a method, so a patch release is semver-compatible.

Generated-by: AI
Signed-off-by: Colin Walters <walters@verbum.org>
@cgwalters-bot cgwalters-bot mentioned this pull request Oct 2, 2026
cgwalters pushed a commit that referenced this pull request Oct 2, 2026
Publish Error::is_retryable() (#155) so that callers such as
composefs-rs can retry transient registry errors without depending on a
git revision. The change only adds a variant to the #[non_exhaustive]
Error enum and a method, so a patch release is semver-compatible.

Generated-by: AI

Signed-off-by: Colin Walters <walters@verbum.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants