Skip to content

Disable Electron auto-updater on Linux (currently relies on a happy accident) #567

@aaddrick

Description

@aaddrick

The static grounding sweep on docs/compat-matrix flagged S26 ("auto-update doesn't fire / corrupt the install") as Missing in build 1.5354.0. Writing it up here so we can pick a fix before it bites us.

What I found

The autoUpdater gate inside the bundled app is structurally open on Linux when app.isPackaged is true:

  • lii() at build-reference/app-extracted/.vite/build/index.js:508761-508774 returns true on Linux when the app is packaged.
  • The truthy path sets the autoUpdater feed URL to api.anthropic.com/api/desktop/linux/... and registers update-check listeners.
  • Our launcher exports ELECTRON_FORCE_IS_PACKAGED=true at scripts/launcher-common.sh:249, so app.isPackaged is true on every install we ship — deb, rpm, AppImage, AUR.

The only reason this doesn't actually try to download anything today is that Electron's Linux autoUpdater is unimplemented. It logs AutoUpdater is not supported on Linux and no-ops. That's a happy accident. If a future Electron bump implements Linux auto-update, or upstream switches to electron-updater, every install in the wild will start hitting that Linux feed URL — and upstream doesn't ship Linux binaries through their feed. Best case: 404s on every check. Worst case: serves something that doesn't match what we shipped, which our installs aren't prepared for.

Case doc with the full anchor list: docs/testing/cases/distribution.md S26.

Two fixes I see

Option 1 — Wrap hA.autoUpdater in frame-fix-wrapper.js to no-op on Linux.

Same pattern as the BrowserWindow defaults override. Smallest diff, lowest risk. Defends against upstream changes regardless of what lii() decides to gate on in a future build.

Option 2 — Gate ELECTRON_FORCE_IS_PACKAGED on the package format in scripts/launcher-common.sh.

Set it true only on AppImage. Leave it unset on deb/rpm where APT/DNF handle updates. More semantically correct — Electron's view of "packaged" lines up with what the user's package manager actually does. Doesn't fix the issue if lii() checks something other than app.isPackaged in a future build.

I'm leaning toward Option 1 because it's defensive and the wrapper already exists for exactly this kind of thing. Option 2 has nicer semantics but a thinner safety margin.

Anyone have a preference, or a third option I'm missing?


Written by Claude opus-4.7 via Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority: mediumShould be addressed when possibletriage: investigatedIssue has been triaged and investigated

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions