
A user pings me: “The app won’t open anymore.”
Classic. I ask the usual: did anything change? “It updated this morning.”
Of course it did.
I remote in and double-click the icon. The cursor does the little spinny thing. The process shows up in Task Manager — CPU ticking, memory allocated, the whole act. But no window. Ever. It just sits there, alive and useless, like a server that boots to a blinking cursor and stops caring.
Kill it. Relaunch. Same thing. Process up, window absent. Reboot the machine. Same thing. Reinstall the app clean. Same. Thing.
That’s the part that bugged me. A fresh install hanging the exact same way means the problem isn’t the binary. The binary is fine. Something outside the binary is poisoning it.
The investigation
When a process starts but never paints a window, it’s usually stuck waiting on something — a lock, a handle, a chunk of state it expects to load. So I stopped staring at the app and started watching what it touched.
Launch ───► Process starts ───► loads cached runtime bundles
│
┌─────┴──────┐
▼ ▼
new v2 binary OLD v1 cache ✗
│ │
└─────┬──────┘
▼
version mismatch ► hang
▼
✗ no window
There it was. The updater swapped the binary to v2 but left a directory of cached runtime bundles from v1 sitting right where the new build looks first. New code, stale cache, two versions trying to share one brain. The app loads the old bundles, chokes on the mismatch, and waits forever for a handshake that’s never coming.
Reinstalling didn’t fix it because reinstalling doesn’t clear that cache. The installer drops a fresh binary and walks away. The landmine stays armed.
The aha
Here’s the tell that saved me: I deleted that cache directory and the app limped to life. Window appeared. It ran. Notably, clearing the cache needed no admin rights — it lives in the user profile, not Program Files. So this isn’t a “corrupt install, nuke from orbit” problem. It’s a “stale state” problem.
But “limped” is the operative word. Deleting the cache once gets you a window, but the app’s background helper service was still holding the old runtime state in memory. It’d rebuild the cache half-correctly and get flaky again. The durable fix was to make the helper rebuild from scratch.
The fix
Order matters. Kill everything first, then clear the cache, then restart the helper so it regenerates clean state, then launch.
# 1. Kill every process the app owns — no orphans holding the cache open
Get-Process -Name "TheApp*" -ErrorAction SilentlyContinue | Stop-Process -Force
# 2. Delete the stale runtime/bundle cache (user profile — no admin needed)
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\TheApp\Cache\bundles" -ErrorAction SilentlyContinue
# 3. Restart the background helper service so it rebuilds state fresh
Restart-Service -Name "TheAppHelper" -Force
# 4. Confirm exactly one helper is up before relaunching
Get-Service -Name "TheAppHelper"
Then launch the app normally. Window paints, app stays up across reboots. Done.
If you skip step 1 and a stray process still has a handle on the cache dir, the delete silently no-ops and you’re right back where you started — wondering why a “fix” did nothing. Clear the orphans first, every time.
Why it happened
Auto-updaters are optimists. They assume the new binary and the old cached state are compatible, so they swap the executable and leave the rest in place to “save time.” Most of the time that’s fine. When the runtime bundle format changes between versions, it absolutely is not — and the app has no graceful path for “my cache is from the future’s past,” so it just hangs.
Reinstalling feels like the big hammer, but it only touches the binary. The poison was always in the user-profile cache the installer never looks at.
Takeaways
- A hang right after an auto-update is stale state, not a corrupt install. Clear the cache and restart the helper before you reinstall.
- A reinstall that changes nothing is a clue, not a dead end — it means the problem lives outside the install footprint.
- Cache/runtime dirs usually sit in the user profile — clearing them needs no admin, so try the cheap fix first.
- Kill orphan processes before deleting their files. A held handle turns your fix into a no-op and wastes an hour.
- Restart the background service, don’t just delete and pray. Deleting the cache gets a window; restarting the helper makes it stay.