Changing "Disk image location" always fails with "copying vm disk with robocopy: exit status 1", even though the copy succeeds
Description
Changing Settings → Resources → Advanced → Disk image location to a folder on a different drive always fails with:
failed to move WSL data: failed to move WSL disk: copying vm disk with robocopy: exit status 1. New setting not applied
The underlying robocopy copy actually succeeds — a complete, correctly-sized copy of docker_data.vhdx is left at the destination — but Docker Desktop reports failure, aborts, and silently reverts to the original (old-drive) location. The orphaned copy at the destination is not cleaned up, so every retry wastes disk space equal to the full data-disk size.
I believe this is because robocopy.exe exit code 1 does not mean failure. Per Microsoft's documented robocopy exit codes, it's a bitmask where:
0 = no files copied, no failure
1 = one or more files copied successfully
2 = extra files/dirs detected
4 = mismatched files/dirs detected
8 = some files/dirs could not be copied (real failure)
16 = serious error, no files copied
Only 8+ indicates an actual problem. Docker Desktop's move logic appears to treat any non-zero exit code from the robocopy subprocess as an error (consistent with Go's exec.Cmd.Run() returning a non-nil *ExitError for any non-zero exit), rather than checking the bitmask per robocopy's own convention. So a "fully successful move" (exit 1) is indistinguishable, from Docker Desktop's point of view, from a real failure.
Reproduction steps
- Have Docker Desktop running normally with the default disk image location (
%LOCALAPPDATA%\Docker\wsl\disk\docker_data.vhdx on C:).
- Go to Settings → Resources → Advanced → Disk image location, click Browse, choose a folder on a different physical drive (e.g.
D:\Docker\wsl-disk).
- Click Apply & restart.
- Wait for the copy to complete (took ~5 minutes for a ~42 GB data disk in my case).
Expected behavior
Docker Desktop restarts using the new disk image location; the old location's docker_data.vhdx is removed (or the docs' stated behavior, whatever that is).
Actual behavior
- Docker Desktop shows a failure and the setting reverts.
- Docker's own log confirms the copy step itself succeeded before this happened.
- The engine keeps running against the old location on the original drive, with no indication to the user that the underlying copy actually finished.
- A complete, correctly-sized copy of
docker_data.vhdx is left behind at the new location, orphaned — not cleaned up, not used.
- This is 100% reproducible: repeated on the same machine twice (including a full Docker Desktop quit + relaunch in between), both attempts failed identically.
Evidence (from %LOCALAPPDATA%\Docker\log\host\com.docker.backend.exe.log)
[...][com.docker.backend.exe.appmanager] moving WSL data from "C:\\Users\\<user>\\AppData\\Local\\Docker\\wsl" to "D:\\Docker\\wsl-disk\\DockerDesktopWSL"
[...][com.docker.backend.exe.appmanager] Data is on a different drive: hard copying the data from <HOME>\AppData\Local\Docker\wsl\disk\docker_data.vhdx to D:\Docker\wsl-disk\DockerDesktopWSL\disk\docker_data.vhdx
[...][com.docker.backend.exe.appmanager] Copying disk image with: C:\WINDOWS\system32\robocopy.exe /MOV /J /NFL /NDL /NJH /NP /R:0 <HOME>\AppData\Local\Docker\wsl/disk D:\Docker\wsl-disk\DockerDesktopWSL/disk docker_data.vhdx
[... ~5 minutes later, matching the time a ~42GB copy would take ...]
[...][com.docker.backend.exe.appmanager][W] failed to move WSL data: failed to move WSL disk: copying vm disk with robocopy: exit status 1. New setting not applied
[...][com.docker.backend.exe.report] reporting error to user: failed to move WSL disk: copying vm disk with robocopy: exit status 1
Verified independently (outside Docker Desktop) that after this "failure," a complete copy of docker_data.vhdx, matching the source's exact byte size, existed at the destination path — consistent with robocopy having exited 1 ("files copied successfully") rather than a real error.
Also verified which copy the running engine actually uses after the "failed" move, by writing data through the engine (starting containers) and comparing LastWriteTime on both files immediately before/after: only the original (old-drive) file's timestamp advanced. The destination copy never changed again after the initial robocopy run completed, confirming the engine reverted to the old location rather than using the new one.
Environment
- Docker Desktop version: 4.83.0
- Docker Engine: 29.6.2
- OS: Windows 11 Home, build 10.0.26200
- Backend: WSL2
- Data disk size at time of reproduction: ~42.6 GB
- Source drive:
C: (NTFS, local SSD) — Destination drive: D: (NTFS, local, ~929 GB free at the time, so not a space issue)
Suggested fix
When checking the result of the robocopy subprocess used for this move, treat exit codes 0–7 as success (per robocopy's own documented bitmask semantics) and only 8+ as a real failure, instead of failing on any non-zero exit code. Additionally, if the move is aborted after the copy step has already completed, the orphaned copy at the destination should be cleaned up rather than left in place.
Changing "Disk image location" always fails with "copying vm disk with robocopy: exit status 1", even though the copy succeeds
Description
Changing Settings → Resources → Advanced → Disk image location to a folder on a different drive always fails with:
The underlying
robocopycopy actually succeeds — a complete, correctly-sized copy ofdocker_data.vhdxis left at the destination — but Docker Desktop reports failure, aborts, and silently reverts to the original (old-drive) location. The orphaned copy at the destination is not cleaned up, so every retry wastes disk space equal to the full data-disk size.I believe this is because
robocopy.exeexit code1does not mean failure. Per Microsoft's documentedrobocopyexit codes, it's a bitmask where:0= no files copied, no failure1= one or more files copied successfully2= extra files/dirs detected4= mismatched files/dirs detected8= some files/dirs could not be copied (real failure)16= serious error, no files copiedOnly
8+ indicates an actual problem. Docker Desktop's move logic appears to treat any non-zero exit code from therobocopysubprocess as an error (consistent with Go'sexec.Cmd.Run()returning a non-nil*ExitErrorfor any non-zero exit), rather than checking the bitmask perrobocopy's own convention. So a "fully successful move" (exit 1) is indistinguishable, from Docker Desktop's point of view, from a real failure.Reproduction steps
%LOCALAPPDATA%\Docker\wsl\disk\docker_data.vhdxonC:).D:\Docker\wsl-disk).Expected behavior
Docker Desktop restarts using the new disk image location; the old location's
docker_data.vhdxis removed (or the docs' stated behavior, whatever that is).Actual behavior
docker_data.vhdxis left behind at the new location, orphaned — not cleaned up, not used.Evidence (from
%LOCALAPPDATA%\Docker\log\host\com.docker.backend.exe.log)Verified independently (outside Docker Desktop) that after this "failure," a complete copy of
docker_data.vhdx, matching the source's exact byte size, existed at the destination path — consistent withrobocopyhaving exited1("files copied successfully") rather than a real error.Also verified which copy the running engine actually uses after the "failed" move, by writing data through the engine (starting containers) and comparing
LastWriteTimeon both files immediately before/after: only the original (old-drive) file's timestamp advanced. The destination copy never changed again after the initialrobocopyrun completed, confirming the engine reverted to the old location rather than using the new one.Environment
C:(NTFS, local SSD) — Destination drive:D:(NTFS, local, ~929 GB free at the time, so not a space issue)Suggested fix
When checking the result of the
robocopysubprocess used for this move, treat exit codes0–7as success (perrobocopy's own documented bitmask semantics) and only8+as a real failure, instead of failing on any non-zero exit code. Additionally, if the move is aborted after the copy step has already completed, the orphaned copy at the destination should be cleaned up rather than left in place.