False 'auto-update failed' notification when already on latest version

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 5 comments · opened Jul 28, 2026

Summary

Claude Code shows a persistent banner: "Auto-update failed — Run claude doctor", but the installation is already on the latest version and no action is required.

Steps to reproduce

  1. Use Claude Code normally (desktop app or CLI).
  2. Observe the "Auto-update failed" notification in the UI.
  3. Run claude doctor as instructed.
  4. Run claude update.

Observed behaviour

claude doctor output:

Last update attempt: failed (install_failed) — 2026-07-28
No installation issues found.

claude update output:

Current version: 2.1.220
Claude Code is up to date (2.1.220)

The binary is already at the latest version (2.1.220). The auto-update mechanism recorded a failed install attempt, but the correct version is already running.

Expected behaviour

If the installed version already matches the latest release, the "auto-update failed" banner should not be shown (or should resolve itself silently). The message is confusing because it implies something is broken when nothing is.

Environment

  • Version: 2.1.220
  • Platform: darwin-arm64
  • Config install method: native
  • Auto-update channel: latest

View original on GitHub ↗

4 Comments

joel-loewenstein · 1 month ago

This is the second time this happened, in addtion to the expectation that this does not surface an error as I am already on the newest version, it is not clear on how to remove the message.

<img width="454" height="63" alt="Image" src="https://github.com/user-attachments/assets/f509d735-4bc7-46d6-8a1f-733992abe576" />

owenbrown · 1 month ago

Hit this too, on the same version. I dug into the logs and I think I have the root cause — it isn't a false positive, the update genuinely fails, but for a reason that has nothing to do with the installation.

Root cause: the updater fires during macOS DarkWake, before the network is up

~/.claude/.last-update-result.json:

{"path":"native","outcome":"failed","status":"install_failed","version_from":"2.1.220","version_to":null,"error_code":null}

version_to is null because it never reached the install step. The debug log shows what actually happened:

[ERROR] Native auto-updater failed: Failed to fetch version from
https://downloads.claude.ai/claude-code-releases/latest after 3 attempt(s):
getaddrinfo ENOTFOUND downloads.claude.ai

DNS is fine on this machine — dig, Node's getaddrinfo, and curl all resolve downloads.claude.ai in ~3ms when the machine is awake. The failures only happen while the lid is shut.

I cross-referenced every auto-updater failure in one day's debug log against pmset -g log. All five landed within seconds of a Power Nap maintenance wake:

| Failure | Time after preceding DarkWake began | Length of that DarkWake |
|---|---|---|
| 1 | +3s | 12s |
| 2 | +2s | 25s |
| 3 | +2s | 2s |
| 4 | +2s | 2s |
| 5 | +2s | DarkWake → FullWake |

Five for five. The 30-minute update timer fires during the brief wake, Wi-Fi and mDNSResponder haven't re-associated yet, and getaddrinfo fails immediately.

Why the retries don't help

All three attempts land inside the same ~2-second dead window:

20:57:17.601 [DEBUG] Version check failed on attempt 1/3, retrying: getaddrinfo ENOTFOUND downloads.claude.ai
20:57:18.185 [DEBUG] Version check failed on attempt 2/3, retrying: getaddrinfo ENOTFOUND downloads.claude.ai
20:57:19.575 [ERROR] Failed to fetch version ... after 3 attempt(s)

~600ms apart, ~2s total — on a 2-second maintenance wake the machine is back asleep before attempt 3 could ever succeed.

The telling part: other subsystems in the same process handle this correctly

Interleaved in that identical window:

20:57:18.153 [DEBUG] [code-session] /bridge request failed: getaddrinfo ENOTFOUND api.anthropic.com
20:57:19.089 [ERROR] SSETransport: Connection error: getaddrinfo ENOTFOUND api.anthropic.com
20:57:19.089 [DEBUG] SSETransport: Reconnecting in 3772ms (attempt 3, 2s elapsed)

api.anthropic.com fails at the same millisecond — this is the whole network stack being down, not anything specific to downloads.claude.ai. SSETransport and remote-bridge back off, reconnect on the next real wake, and never bother the user. The updater alone treats a transient resolver failure as terminal and raises a sticky banner that's still sitting there when you open the lid an hour later.

Suggestions

  1. Treat ENOTFOUND/EAI_AGAIN on the version fetch as retryable-later rather than a failed update — don't record install_failed or surface a banner for it. It's indistinguishable from "offline", which is a normal state for a laptop.
  2. Skip or defer the scheduled check when the machine isn't in a full wake state, or when a sibling connection has just reported a DNS failure.
  3. Spread the 3 retries over a much longer window (the SSE backoff already gets this right), and/or clear the banner automatically once a later check succeeds.

Secondary: "autoUpdates": false appears to be ignored on native installs

Related, and probably worth its own issue, but it's why this was hard to get rid of. This config has had "autoUpdates": false in ~/.claude.json for a long time, alongside "installMethod": "native", and the updater still runs every 30 minutes.

There's a config key named autoUpdatesProtectedForNative that sits adjacent to installMethod and autoUpdates, which suggests native installs deliberately override the autoUpdates setting. Whatever the reason for that, it's silent — the setting stays false in the config file and reads as though it's in effect. Either honoring it or warning that it's been overridden would help. (See also #56723, closed, on this same setting being undocumented.)

Environment

  • Version: 2.1.220, native install
  • macOS 26.1, arm64
  • Reproduces whenever the lid is shut and Power Nap triggers a maintenance wake
g-i-o-r-g-i-o · 1 month ago

This looks like the same bug as #65093 (filed 2026-06-03, labelled bug / has repro / regression / area:installation), which has a deterministic repro and the diagnosis: on an install already at the latest version, a failed update check — e.g. the network dropping mid-session — is recorded as install_failed with version_to: null, meaning no install was ever attempted. The record is then never reset by a later successful check, so the banner survives reconnection and restarts.

That matches your output exactly: install_failed on 2.1.220 while claude update reports the binary is already up to date. Workaround until it is fixed: delete ~/.claude/.last-update-result.json (neither claude doctor nor claude update clears it).

See also #82408 and #70608 for the "stale record never self-heals" half. Cross-linking so these don't stay split.

rodlunt · 1 month ago

Same symptom, adding a repro with the underlying state file contents plus one data point I haven't seen mentioned yet.

Environment: Linux x64 (Ubuntu), native install, 2.1.220, channel latest.

Symptom: claude doctor kept reporting a failed auto-update while claude update simultaneously reported:

Current version: 2.1.220
Checking for updates to latest version...
Claude Code is up to date (2.1.220)

(exit 0)

What doctor was reading: ~/.claude/.last-update-result.json contained:

{"timestamp":"2026-07-31T22:41:33.024Z","path":"native","outcome":"failed","status":"install_failed","version_from":"2.1.220","version_to":null,"error_code":null}

version_to: null and error_code: null suggest the background check failed before it even resolved a target version (transient network at session start is my guess), and that got recorded as a hard install_failed.

Two observations:

  1. A successful "already up to date" check does not overwrite the result file. Only an actual install writes a fresh outcome, so with no newer release available the stale failure persists indefinitely and every doctor run re-reports it.
  2. At the time of the failure the release channel pointers were stable = 2.1.212 and latest = 2.1.220, i.e. the installed version was ahead of the stable pointer. Probably irrelevant given the null target, but noting it since none of the related issues (#65093, #66208) mention the channel-pointer state.

Workaround: deleting ~/.claude/.last-update-result.json cleared the banner; doctor then shows Last update attempt: none recorded and No installation issues found. Obviously this just clears the stale record rather than fixing the write logic, so it may recur on the next misfiring background check.

Host-side causes ruled out before concluding it was this bug: versions dir and ~/.local/bin both user-writable, 800G+ free disk, no staging leftovers, and the only lock in ~/.local/state/claude/locks belonged to the live session PID.

Showing cached comments. Read the full discussion on GitHub ↗