How Docker Desktop's Crash Recovery Became a Restart Loop
How Docker Desktop’s Crash Recovery Became a Restart Loop
TL;DR: Docker Desktop crashed, then refused to start again — forever. The root cause was its own crash-recovery feature restoring corrupted files on every boot. The fix: rename the parent directories instead of trying to delete the broken files.
I spent a morning fighting Docker Desktop. It wouldn’t start. Every attempt returned the same error. Nothing I tried worked — and the more I dug in, the stranger it got.
This is what I found.
It Just Kept Crashing
The error looked straightforward at first:
starting services: initializing Inference manager: listening on unix://<user-home>\AppData\Local\Docker\run\dockerInference:
remove <user-home>\AppData\Local\Docker\run\dockerInference: The file cannot be accessed by the system.
Something about a socket file Docker couldn’t remove. Fine — I’ll delete it myself.
Except I couldn’t delete it either. Not with Remove-Item. Not with takeown. Not with fsutil reparsepoint delete. Not with anything. Every single attempt returned the same error: ERROR_FILE_INVALID.
That’s when the situation changed from “annoying” to “interesting.”
Why Deletion Was Impossible
The file dockerInference isn’t a regular file. It’s a Windows reparse point — a special filesystem object that works like a pointer, redirecting I/O to a target somewhere else.
Docker uses these to implement Unix-style sockets inside WSL2. When WSL2 crashed (mine did, probably during a sleep/wake cycle), the pointer’s target disappeared. The file itself still exists in the directory. But it points to nothing.
Windows can’t read through a broken pointer. So every deletion attempt fails with error 1920, regardless of permissions or administrator rights. The filesystem has made its decision — the target is gone, deletion is impossible.
Rename the Parent, Don’t Delete the File
Here’s the key insight: renaming a directory doesn’t need to read its contents.
A rename only touches the parent directory’s metadata. The broken reparse point inside? Doesn’t matter. The operation never tries to access it.
So instead of fighting the broken file, I renamed the folder around it.
One elevated PowerShell session:
Rename-Item '<user-home>\AppData\Local\Docker\run' 'run.stale'
Docker started. Success — for about 30 seconds. Then it crashed again on a different socket.
The Loop Nobody Told Me About
After the fifth crash-rename-restart cycle, the pattern became obvious: Docker was recreating the broken sockets every time.
I looked inside %LOCALAPPDATA%\Docker\ and found backup directories:
run.bak-20260508085258run.bak-20260508085919
Both full of the same broken socket files.
Docker Desktop has an undocumented crash-recovery feature. On startup, it backs up the entire run/ directory with a timestamp. If it crashed last time, it restores from the most recent backup — trying to preserve container state and socket handles.
This sounds helpful. In this case, it was the problem.
The backup only contained corruption. So on every single restart:
- Docker finds the most recent backup
- Silently restores it to
run/ - Tries to remove the broken socket
- Fails (error 1920)
- Crashes
- Repeat
Renaming run/ bought me 30 seconds — just long enough for Docker to restore the backup and recreate the broken state.
The Actual Fix
Rename everything. The live directory and all the backups.
Rename-Item '<user-home>\AppData\Local\Docker\run' 'run.stale'
Rename-Item '<user-home>\AppData\Local\Docker\run.bak-20260508085258' 'run.bak-20260508085258.stale'
Rename-Item '<user-home>\AppData\Local\Docker\run.bak-20260508085919' 'run.bak-20260508085919.stale'
Rename-Item '<user-home>\AppData\Local\docker-secrets-engine' 'docker-secrets-engine.stale'
Rename-Item '<user-home>\AppData\Local\docker-secrets-engine.bak-20260508085459' 'docker-secrets-engine.bak-20260508085459.stale'
After that, Docker started cleanly and rebuilt everything from scratch.
The Lesson
Two things broke here, and both are worth remembering.
On the filesystem side: Windows error 1920 on a reparse point means the target is gone. Don’t try harder to delete — it won’t work. Rename the parent directory instead. The operation doesn’t need to read the file.
On the recovery system side: A backup that restores corrupted state isn’t a safety net — it’s a trap. If a process crashes because cleanup failed, restoring that same state just recreates the crash. Recovery only helps when the state it’s restoring is actually recoverable.
Current Status
The Docker team is aware of the underlying issue (docker/desktop-feedback#342, reported May 5). No fix has shipped as of version 4.72.0.
Disabling inference in admin-settings.json doesn’t help — Docker ignores the flag during service initialization. A fresh install doesn’t help either — it recreates the problem from the same broken WSL snapshot.
If you’re in this loop: stop trying to delete. Rename the parent directories — all of them, including the backups — and let Docker rebuild clean.