Don't report cancelled remote transfers as errors - #30652
Open
fmeum wants to merge 3 commits into
Open
Conversation
When a bulk transfer to or from the remote cache is cancelled, e.g. because the action owning it is interrupted, every one of its in-flight transfers fails with a `CancellationException`. `mergeBulkTransfer` subscribes to all of them at once via `flatMapSingle`, which terminates on the first error and hands all subsequent ones to RxJava's global error handler. `RemoteModule` installs a handler that reports those as error events, so a single cancelled bulk transfer printed a `java.util.concurrent.CancellationException: Task was cancelled` stack trace for every transfer but the first. A transfer is only ever cancelled as part of tearing down the operation it belongs to, so `toTransferResult` now maps `CancellationException` to the same result as `InterruptedException` instead of propagating it. Also replaces two `isDisposed()`-then-`onError()` sequences with `tryOnError`: the emitter can be disposed in between, in which case `onError` hands the error to the global error handler as well.
fmeum
marked this pull request as ready for review
August 10, 2026 12:47
Collaborator
Author
|
@bazel-io fork 9.3.0 |
coeuvre
approved these changes
Aug 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
When a bulk transfer to or from the remote cache is cancelled, every one of its in-flight transfers fails with a
CancellationException.mergeBulkTransfersubscribes to all transfers of a bulk operation at once viaflatMapSingle, which terminates on the first error and hands every subsequent one to RxJava's global error handler.RemoteModuleinstalls a global error handler that reports those as error events, so a single cancelled bulk transfer printed ajava.util.concurrent.CancellationException: Task was cancelledstack trace for every transfer but the first.A transfer is only ever cancelled as part of tearing down the operation it belongs to, so
toTransferResultnow mapsCancellationExceptionto the same result asInterruptedExceptioninstead of propagating it downstream.This PR also replaces two
isDisposed()-then-onError()sequences inRxFuturesandAsyncTaskCachewithtryOnError. Those checks aren't atomic with the delivery: the emitter can be disposed in between, in which caseonErrorhands the error to the global error handler as well.Motivation
Users see spurious
ERROR: java.util.concurrent.CancellationException: Task was cancelledstack traces, one per concurrently cancelled transfer, whenever a build that is uploading or downloading blobs is interrupted or an action fails while a bulk transfer is in flight.This also shows up as a flake in
RemoteExecutionServiceTest.uploadInputsIfNotPresent_interrupted_requestCancelled, which fails wheneverRxNoGlobalErrorsRuleobserves the leaked exception. That test failed in roughly 2-5% of runs before this change and passed 100 out of 100 times after it.Build API Changes
No
Checklist
The existing
uploadInputsIfNotPresent_interrupted_requestCancelledcovers this, but only probabilistically: the number of transfers that are cancelled concurrently determines whether an error is leaked, and thetryOnErrorchanges fix races that can't be triggered deterministically.Release Notes
RELNOTES: None