[Bug] Multiple concurrent instances cause version downgrade (2.0.70 → 2.0.65)
Description
When running multiple Claude Code instances simultaneously, the auto-update mechanism can downgrade the symlink to an older version instead of maintaining the newest installed version.
Observed Behavior
- Version 2.0.70 was downloaded and installed at 10:22
- At 10:48, the symlink was changed to point to 2.0.65 (an older version)
- 8 concurrent Claude Code instances were running at the time
Evidence
Installed versions:
$ ls -la ~/.local/share/claude/versions/
-rwxr-xr-x 1 tim tim 211547692 Dec 4 08:34 2.0.58
-rwxr-xr-x 1 tim tim 205340223 Dec 11 15:16 2.0.65
-rwxr-xr-x 1 tim tim 207455556 Dec 12 14:00 2.0.67
-rwxr-xr-x 1 tim tim 207576789 Dec 13 11:31 2.0.69
-rwxr-xr-x 1 tim tim 212229481 Dec 16 10:22 2.0.70 ← newest
Symlink points to older version:
$ ls -la ~/.local/bin/claude
lrwxrwxrwx 1 tim tim 45 Dec 16 10:48 /home/tim/.local/bin/claude -> /home/tim/.local/share/claude/versions/2.0.65
Concurrent instances running:
$ pgrep -a claude
1891488 claude
2553510 claude --resume
2554915 claude --resume
2555979 claude --resume
2557322 claude --resume
2558340 claude --resume
2563536 claude
2563997 claude
Lock files show activity for both versions:
$ ls -la ~/.local/state/claude/locks/
drwxrwxr-x 2 tim tim 4096 Dec 9 14:44 2.0.58.lock
drwxrwxr-x 2 tim tim 4096 Dec 16 10:51 2.0.65.lock
drwxrwxr-x 2 tim tim 4096 Dec 16 10:40 2.0.70.lock
Expected Behavior
When multiple instances race to update the symlink, the updater should:
- Compare version numbers before changing the symlink
- Never downgrade to an older version
- Use atomic operations or proper locking to prevent races
Root Cause Hypothesis
The update mechanism appears to:
- Download a new version
- Update the symlink to point to the downloaded version
When multiple instances run concurrently, an older instance that started its update earlier may complete its symlink update after a newer instance, overwriting the symlink with an older version.
Suggested Fix
Before updating the symlink, compare the target version against the current symlink target:
# Pseudocode
current_version = readlink(~/.local/bin/claude) | extract_version
new_version = downloaded_version
if semver_compare(new_version, current_version) > 0:
atomic_symlink_update(new_version)
else:
skip_symlink_update() # Already on newer version
Environment
- Platform: Linux (Ubuntu 24.04)
- Kernel: 6.14.0-36-generic
- Architecture: x86_64
- Node.js: v18.19.1
- Shell: bash
- Installation method: Native installer (symlink-based)
Related Issues
- #12444 - Auto-update fails with ENOTEMPTY when multiple CLI instances are running
- #7373 - (duplicate target of #12444)
- #2561 - Something keeps installing old version of Claude every day
- #13280 - Multiple Claude Code instances fail after update to 2.0.60
- #13705 - Update process leaves stale lock file, blocking subsequent updates
Workaround
Manually fix the symlink:
ln -sf ~/.local/share/claude/versions/2.0.70 ~/.local/bin/claude