Empty imports after a refused move

Reproduced with rclone 1.72.0, a local-first union, VFS full caching and the .NET 6 File.Move(source, destination) used by Sonarr 4.0.19.2979.

When the backend refuses a MOVE, rclone's vfs.File.rename leaves the file's directory and name pointing at the attempted destination. .NET then falls back to a copy. Creating its destination creates an empty VFS cache entry; opening the source reaches that same entry, so the copy reads EOF and reports success. The reproduction expected 4096 bytes and received zero. Changing the WebDAV refusal from 409 to 422 did not change the outcome.

The patch in scripts/patches/rclone-v1.72.0-rename.patch restores the original directory and name when the immediate rename fails. It includes an upstream VFS regression test. The mount test exercises the full WebDAV, union, FUSE and .NET path with a fake archive and no provider credentials. Its damage verdict is injected while the fixture bytes remain readable: .NET may copy those bytes successfully, but must not turn them into an empty file.

Build a new binary alongside the installed one:

./scripts/build-rclone-move-fix.sh /absolute/path/to/rclone-fixed
RCLONE_TEST_BIN=/absolute/path/to/rclone-fixed ./integration/magic_move_refusal.sh

The build pins upstream commit 38ab3dd5b1df946aecf5bd085c671c86f46f68eb (1.72.0). It runs the VFS rename tests before building. The mount test requires Linux FUSE and Docker, or a self-contained DOTNET_MOVE_PROBE_BIN built from integration/dotnet-move-probe. It intentionally fails against the unpatched binary. make integration-test includes this check; point RCLONE_TEST_BIN and RCLONE_BIN at the corrected binary when running the suite.

Installation requires restarting the mount using the deployment's normal media-server guards. Keep the previous binary for rollback. Existing empty files on a union's local upstream survive a mount restart; preserve and remove only confirmed empty import artifacts there. Restarting clears the stale VFS nodes, but does not repair missing Usenet articles.

This correction does not suppress .NET's copy fallback or make damaged content readable. zurg's availability check before SABnzbd completion and its refused MOVE remain separate protections. Availability sampling is not a full-file verification; see sabnzbd-client-contract.md.

The pinned patch also carries the file-alias correction used by the embedded union. With action_policy: all, local and WebDAV can both receive a file operation. A successful local Move or Remove paired with a WebDAV 404 is accepted only after a fresh lookup proves that the failed upstream's source is gone; all-failed operations, a source that still exists, a missing destination parent, and other I/O or permission errors remain failures. The resulting binary reports v1.72.0-zurg-rename-sidecar-fix so it is distinguishable from the original VFS-only build.