Windows native: claude update reports success but bin\claude.exe is never replaced (HOME unset - not the HOME/USERPROFILE split-brain case)
Environment
- OS: Windows 11 Pro (10.0.26200), AMD64
- Install method: native installer
- Affected version: 2.1.183 (stuck); updater targets 2.1.185
- Node: v24.8.0
USERPROFILE = C:\Users\<user>(standard)HOMEis NOT set (empty) — this is what distinguishes this report from theHOME != USERPROFILEsplit-brain bugs (#46271, #65391).- Config:
"installMethod": "native","autoUpdates": false,"autoUpdatesProtectedForNative": true
Summary
On a Windows native install where HOME is unset, claude update printsSuccessfully updated from X to version Y but the launched binary at%USERPROFILE%\.local\bin\claude.exe is never replaced. The new version is
downloaded correctly into %USERPROFILE%\.local\share\claude\versions\Y, but theversions\Y -> .local\bin\claude.exe copy step does not happen. claude --version
stays at the old version forever, across any number of claude update runs and
restarts.
This is not the HOME != USERPROFILE split-brain case (#46271 / #65391):
the updater writes to the same .local tree the binary lives in. Both the
downloaded version and the running binary are under C:\Users\<user>\.local\.
The failure is the same-tree self-replace step, not a path-resolution mismatch.
Evidence (this machine)
# 1) Downloaded version exists and is genuinely the new build
versions\2.1.185 ProductVersion 2.1.185.0 SHA256 0206CFB9...
versions\2.1.183 ProductVersion 2.1.183.0 SHA256 BA6E71D0...
# 2) The running binary is byte-identical to the OLD version, not the new one
bin\claude.exe ProductVersion 2.1.183.0 SHA256 BA6E71D0... (== versions\2.1.183)
bin\claude.exe LastWriteTime never changes after update (frozen at install day)
# 3) update reports success but bin is untouched
$ claude update
Current version: 2.1.183
Checking for updates to latest version...
Updating to 2.1.185...
Successfully updated from 2.1.183 to version 2.1.185
$ claude --version
2.1.183 (Claude Code) # <- unchanged
# 4) No split-brain: nothing is written under C:\.local or any HOME-derived path.
# The new 2.1.185 lands in the correct C:\Users\<user>\.local\share\claude\versions\.
The downloaded versions\2.1.185 binary is verified by hash + embeddedProductVersion to be the real 2.1.185. The only thing missing is the final
copy/replace into bin\claude.exe.
Two defects
- Same-tree self-replace silently fails. Even though install root resolution
is correct (no HOME involved, everything under %USERPROFILE%\.local), the
updater does not end up replacing bin\claude.exe with the freshly downloaded
versions\<new>. On Windows the running claude.exe is exclusively locked by
the live session, so an in-place overwrite would fail — but a correct updater
should use the rename-then-copy trick (rename the in-use exe, copy the new one
in) and/or report the lock loudly.
- False success report.
claude updateprints
Successfully updated from X to version Y without verifying that the binary it
was launched from (or the one on PATH) actually changed. The binary even
contains the strings windows_running_exe_lock / update_apply_exe_locked and
an error path Error: Update failed because claude.exe is in use. Close other — but that error path is
Claude Code sessions ... then run claude update again
not taken; success is reported instead.
Expected
- After
claude updatereports success,claude --versionreflects the new version. - If the running
claude.exeis locked (live session / VS Code), the updater
should either perform a rename-then-copy replace, or fail loudly with the
existing claude.exe is in use message — not report success.
claude doctorshould detect whenbin\claude.exe's version is older than the
newest entry in versions\ (drift detection).
Repro
- On Windows, native-install Claude Code with
HOMEunset (default for most users). - Run
claude updatewhile a Claude Code session is running (the normal case —
you typically run claude update from within or alongside a live session).
- Observe:
Successfully updated from X to Y, a newversions\Yappears under
%USERPROFILE%\.local\share\claude\versions\, but claude --version is unchanged
and bin\claude.exe is byte-identical to the old versions\X.
Related
- #46271 — update fails when
$HOMEis modified (closed) - #65391 — native updater resolves install root via
HOMEwhile launcher uses
USERPROFILE (closed as dup of #46271; reporter notes it should stay open)
This report is the HOME-unset variant: path resolution is correct, yet the
same-tree versions\ -> bin\ replace still does not happen and success is still
reported. That points at the self-replace / verification step itself rather than
path resolution.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗