vfs/vfscache: don't discard a clean cached file when the remote lookup is unconfirmed by sjluppino · Pull Request #9531 · rclone/rclone · GitHub
Skip to content

vfs/vfscache: don't discard a clean cached file when the remote lookup is unconfirmed#9531

Open
sjluppino wants to merge 1 commit into
rclone:masterfrom
sjluppino:fix-9530-vfs-cache-unconfirmed-remote
Open

vfs/vfscache: don't discard a clean cached file when the remote lookup is unconfirmed#9531
sjluppino wants to merge 1 commit into
rclone:masterfrom
sjluppino:fix-9530-vfs-cache-unconfirmed-remote

Conversation

@sjluppino

Copy link
Copy Markdown

In _checkObject, a nil remote object was treated as a confirmed deletion and the clean cached file was removed (stale (remote deleted)), so the next read returned 0 bytes. But o is also nil when the directory listing was successful but incomplete — an eventually-consistent backend, a stale negative right after a remount, or a proxy returning empty-without-error — so o == nil arrives with no error to signal it. (A genuine connection failure already surfaces as an I/O error via list.DirSorted, so that case isn't affected.)

This re-confirms with NewObject before acting on the nil, the same pattern the download path already uses (#6190/#6235):

  • ErrorObjectNotFound / ErrorIsDir → remove as before (deletion propagation preserved)
  • other (transient) error → keep the cached file; its fingerprint matched when written, so serving it is safe (logged at INFO — happy to return the error instead if you'd prefer)
  • success → fingerprint-check it like the normal path

It does not cure eventual consistency: if both the listing and the NewObject HEAD return a stale negative in the same window, the item is still discarded. It fixes the transient-error and "list stale but HEAD authoritative" cases.

Adds two tests (transient → kept, ErrorObjectNotFound → removed) and TestItemReloadRemoteGone still passes as the deletion-propagation regression guard.

Fixes #9530

…p is unconfirmed

_checkObject treated a nil remote object as a confirmed deletion and removed the
clean cached file ("stale (remote deleted)"), so the next read returned 0 bytes.
But o is also nil when the directory listing was successful but incomplete - an
eventually consistent backend, a stale negative right after a remount, or a proxy
returning empty without an error - so o == nil arrives with no error to signal it.
A genuine connection failure already surfaces as an I/O error via list.DirSorted,
so that case is unaffected.

Re-confirm with NewObject before acting on the nil, the same way the download path
already does:

  - ErrorObjectNotFound / ErrorIsDir -> remove as before (deletion propagation)
  - other (transient) error -> keep the cached file; its fingerprint matched when
    written, so serving it is safe
  - success -> fingerprint-check it like the normal path

This does not cure eventual consistency: if both the listing and the NewObject HEAD
return a stale negative in the same window, the item is still discarded.

Fixes rclone#9530

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

VFS cache (--vfs-cache-mode full): clean item discarded when the remote is unreachable (treated as deleted) -> transient 0-byte read

1 participant