Auto-update silently fails when npm global folder isn't writable, then forces re-login on next run
Title
Auto-update silently fails when npm global folder isn't writable, then forces re-login on next run
Description
On a system where the npm global install directory isn't writable by the running user, claude update (and presumably the background auto-updater) fails to install the new version — but the failure isn't clearly surfaced, and afterwards I'm forced to fully re-authenticate (/login) even though my previous session and refresh token were still valid.
This happened repeatedly across multiple update cycles before I diagnosed the root cause.
Environment
- Claude Code version at time of issue: 2.1.220 (npm global install)
- OS: Linux (Ubuntu, systemd)
- Auth method: Claude subscription (OAuth login, not API key)
- npm global prefix:
/usr/local, owned bynobody:nogroup(not writable by the invoking user)
Steps to reproduce
- Install Claude Code via npm global (
npm install -g @anthropic-ai/claude-code) on a system where/usr/local/lib/node_modulesis not writable by your user. - Log in normally via
/loginwith a Claude subscription. - Run
claude update(or wait for background auto-update). - Observe:
````
Warning: Can't auto-update: npm global folder isn't writable
Fix: Run claude install to switch to the native installer (no sudo)
New version available: 2.1.231 (current: 2.1.220)
Installing update...
Using global installation update method...
Error: Failed to install update
- Start
claudeagain — prompted to log in again, despite the previous session working fine and the refresh token still being valid.
Diagnostic details
Inspecting ~/.claude/.credentials.json around the time of the forced logout showed:
claudeAiOauth.expiresAt=0claudeAiOauth.refreshTokenExpiresAt= a valid future timestamp (~15 days out)
Note: after switching to the native installer (claude install), the same credentials file (same expiresAt: 0, unchanged mtime) continued to work without forcing a re-login — so expiresAt: 0 on its own does not appear to be the trigger. The forced re-login seems tied specifically to the failed/partial auto-update attempt on the unwritable npm global install, not to the credentials file contents.
Also checked and ruled out
- System clock: NTP active, offset ~1.4s — not the cause.
~/.claude/.credentials.jsonpermissions: correct (0600, owned by the running user).
Suggested fix
- When auto-update detects an unwritable npm global folder, fail gracefully without touching the stored session/credentials, and surface a clear one-time notice to run
claude install— rather than leaving the CLI in a state that later forces a full re-login. - Consider proactively detecting this on first run (unwritable global npm folder) and recommending the native installer before the user hits a failed update.
Workaround
Switching to the native installer resolved it:
claude install