Windows native: claude update reports success but bin\claude.exe is never replaced (HOME unset - not the HOME/USERPROFILE split-brain case)

Open 💬 3 comments Opened Jun 21, 2026 by albert-rim

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)
  • HOME is NOT set (empty) — this is what distinguishes this report from the HOME != USERPROFILE split-brain bugs (#46271, #65391).
  • Config: "installMethod": "native", "autoUpdates": false, "autoUpdatesProtectedForNative": true

Summary

On a Windows native install where HOME is unset, claude update prints
Successfully 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 the
versions\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 + embedded
ProductVersion to be the real 2.1.185. The only thing missing is the final
copy/replace into bin\claude.exe.

Two defects

  1. 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.

  1. False success report. claude update prints

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
Claude Code sessions ... then run claude update again
— but that error path is
not taken; success is reported instead.

Expected

  • After claude update reports success, claude --version reflects the new version.
  • If the running claude.exe is 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 doctor should detect when bin\claude.exe's version is older than the

newest entry in versions\ (drift detection).

Repro

  1. On Windows, native-install Claude Code with HOME unset (default for most users).
  2. Run claude update while a Claude Code session is running (the normal case —

you typically run claude update from within or alongside a live session).

  1. Observe: Successfully updated from X to Y, a new versions\Y appears 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 $HOME is modified (closed)
  • #65391 — native updater resolves install root via HOME while 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.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗