fs/chunkedreader: fix spurious errors when a parallel stream is closed early

Closing a stream in the parallel chunked reader cancels the stream's
context, so the in-flight read returns context.Canceled. This was wrapped
and returned as "failed to read stream", which the VFS cache downloader
treats as a real download error - it only recognises
asyncreader.ErrorStreamAbandoned as a benign teardown, as returned by the
sequential reader.

Return asyncreader.ErrorStreamAbandoned for a cancellation so tearing down
the parallel reader (on close, seek or reposition) is recognised as benign,
matching the sequential reader, instead of logging download errors and
retrying when --vfs-read-chunk-streams is used with --vfs-cache-mode full.
This commit is contained in:
Nick Craig-Wood
2026-07-03 15:37:09 +01:00
parent 6e0cde076a
commit ed9eec0f20

View File

@@ -2,11 +2,13 @@ package chunkedreader
import (
"context"
"errors"
"fmt"
"io"
"sync"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/asyncreader"
"github.com/rclone/rclone/fs/hash"
"github.com/rclone/rclone/fs/log"
"github.com/rclone/rclone/fs/operations"
@@ -136,6 +138,14 @@ func (s *stream) close() (err error) {
if s.rc != nil {
orErr(&err, s.rc.Close())
}
// close cancels the stream's context above, so a cancellation error
// just means the stream was intentionally abandoned. Report that as
// asyncreader.ErrorStreamAbandoned - the same signal the sequential
// reader uses - so callers (e.g. the VFS cache downloader) treat it as
// a benign teardown rather than a read failure.
if errors.Is(err, context.Canceled) {
return asyncreader.ErrorStreamAbandoned
}
if err != nil && err != io.EOF {
return fmt.Errorf("parallel chunked reader: failed to read stream at %d size %d: %w", s.offset, s.size, err)
}