fix(desktop): build AppImage with the static runtime toolset (fixes libfuse2 launch failure) - #7765
Conversation
electron-builder defaults `toolsets.appimage` to the legacy "0.0.0" bundle, whose type-2 runtime is dynamically linked against libfuse.so.2. Distros that ship only FUSE 3 cannot mount it, so the AppImage exits before Electron starts. Pin the 1.0.3 bundle (runtime 20251108), which is statically linked and needs no FUSE. Scoped to the linux branch so mac/win toolsets are unchanged.
electron-builder defaults `toolsets.appimage` to the legacy "0.0.0" bundle, whose type-2 runtime is dynamically linked against libfuse.so.2. Distros that ship only FUSE 3 cannot mount it, so the AppImage exits before Electron starts. Pin the 1.0.3 bundle (runtime 20251108), which is statically linked and needs no FUSE. Scoped to the linux branch so mac/win toolsets are unchanged.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This change pins the AppImage toolset version to fix a libfuse2 dependency issue on newer Linux distros. It's a minor build configuration tweak with no runtime behavior impact, includes test coverage, and is well-documented. You can add or adjust custom eligibility rules. Learn more. |
Problem
The Linux AppImage cannot launch on any distro that has dropped FUSE 2. It dies before Electron starts:
I'm on Linux and the AppImage is how I run T3 Code, so this takes the app out entirely. On Debian forky there is no local fix —
libfuse2/libfuse2t64has been removed from the archive (apt-cache policyreturns no candidate), so thesudo apt install libfuse2workaround from the existing issues simply doesn't apply. FUSE 2 is EOL upstream, so more distros will land here over time, not fewer.Previously reported in #1482 and #4465 (the latter open since July with no response).
Cause
Not the app — the packaging default. In
app-builder-lib26.15.6 (the version pinned inapps/desktop/package.json) the runtime is selected by:Unset/
nullselects the legacy FUSE 2 bundle.toolsetsappears nowhere in this repo, so builds silently inherit that default.Fix
Pin the static toolset, which
app-builder-lib26.15.6 already supports — no dependency bump required:Set inside the
platform === "linux"branch, so macOS and Windows toolsets are untouched.electron-builder v27 flips this default (
isFuse2 = toolset === "0.0.0", explicit opt-in only) via the toolset overhaul in #9939. This brings the fix forward without waiting on the v27 breaking release.Verification
The runtime actually changes. I downloaded the
1.0.3toolset and confirmed its SHA-256 matches theappimageChecksums["1.0.3"]entry inapp-builder-lib26.15.6 (84021a78…c7fe0→84021a78ee214ae6fd33a2d62a92ba25542dd10bc86bf117a9b2d0bba44e7665), then compared runtimes:0.0.34-nightly.20260821.11491.0.3(runtime 20251108)libfuse.so.2The current runtime carries
libfuse.so.2and thedlopen()error string; the proposed one is statically linked and has no FUSE dependency at all.Tests (
scriptsworkspace,vp test run):build-desktop-artifact.test.ts— 46/46 pass with the change.expected undefined to deeply equal { appimage: '1.0.3' }, so the assertion is meaningful rather than vacuous.scriptssuite — 234/235 pass. The single failure islib/cli-external-packages.test.ts("expected node-pty in the pnpm store"), which is an artifact of my filteredpnpm install --ignore-scriptsand reproduces identically on pristinemainwith this PR's changes reverted. Unrelated to this change.tsgo --noEmitonscripts— clean, exit 0.End-to-end packaged build. I ran
node scripts/build-desktop-artifact.ts --platform linux --target AppImage --arch x64on Debian forky (FUSE 3 only, nolibfuse2installed anywhere on the system). It completed cleanly, exit 0, producing a 143 MBT3-Code-0.0.33-x86_64.AppImage. Its runtime isstatic-pie linked, BuildIDa87aaf5da1…, matching the 1.0.3 runtime exactly.The resulting AppImage mounts on a machine where the current release cannot — same host, same flag, back to back:
mountconfirms a real FUSE mount, and Electron boots from it (AppRunoff the mountpoint initialises its user-data dir). My run then exits via the existing single-instance lock because another copy was already running on this box — the behaviour described in #4465 — so I have not verified a full cold UI session end to end, only that the runtime mounts and the app starts from it. That is precisely the part this PR changes.Still worth confirming in CI: the
electron-updaterAppImageUpdaterin-place update path, since the runtime is what gets swapped.Note on the toolset version
1.0.2/1.0.3are labelled "Betas" in electron-builder's typings (1.0.3notes it resolves electron-builder#9598). If you'd rather not ship a beta toolset, the alternative is waiting for v27 — but that leaves the AppImage unlaunchable on modern distros until then.For anyone hitting this before a release:
APPIMAGE_EXTRACT_AND_RUN=1works around it without root, since it skips mounting entirely.🤖 Generated with Claude Code