[Bug]: Linux AppImage: desktop main process exits silently (no quit lifecycle, no core), AppImage mount disappears and all children die with SIGBUS#14259

openedSep 29, 2026byOorlandoflowers

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/desktop

Steps to reproduce

I don't have a deterministic repro yet. It happens intermittently while the app is simply running (sometimes after ~15 minutes, sometimes after days), with no user action at the time.

  1. Launch the Linux AppImage (<appimage-dir>/t3code.AppImage --no-sandbox, started through a .desktop entry via gtk-launch on Hyprland/Wayland), update channel latest.
  2. Leave it running with one or more threads/terminals open.
  3. At some point the whole app disappears without warning.

This happened 3 times on 2026-09-28 (17:25, 18:21, 20:34 local time, UTC-3). I also have earlier SIGBUS cores with the same signature from 2026-09-16, 09-22 and 09-23.

Expected behavior

The app keeps running. If the main process has to exit, it goes through the normal shutdown path (windowAllClosed / beforeQuit / requestShutdownAndWait) and logs why.

Actual behavior

The Electron main process disappears abruptly:

  • desktop.trace.ndjson shows no lifecycle spans (windowAllClosed, beforeQuit, requestShutdownAndWait) for these exits. When I close the window normally, those spans do show up (e.g. 2026-09-28 17:39:04 and 2026-09-29 09:27:31).
  • There is no core dump for the main process (systemd-coredump is active and catches the children), and there is no minidump in ~/.config/t3code/Crashpad (only client_id).
  • Within ~1s the AppImage FUSE mount (/tmp/.mount_t3codeXXXXXX) is torn down, and every remaining child (renderer, GPU process, network utility, and the apps/server/dist/bin.mjs backend) dies with SIGBUS (BUS_ADRERR) because its mapped files are gone.

So the SIGBUS cores are a symptom. The actual event is the main process exiting without going through the shutdown path. Any running agent sessions and terminals are killed with it.

Timing relative to the update poller. The poller runs desktop.updates.checkForUpdates every 4 minutes, and all three exits land near a poll. Only one is a clear match:

Exit (mount gone)Nearest update-check activityRelationship
18:21:10.27handleCheckingForUpdate at 18:21:09.585; parent checkForUpdates span never endedexit 0.7s into an update check
20:34:01.57previous check 20:30:00.962 → 20:30:01.680; next one due ≈20:34:01.68 by the 4-min cadence, no span loggedexit ~0.1s before the scheduled poll
17:25:09.65checkForUpdates 17:25:04.179 → 17:25:04.986, Success / handleUpdateNotAvailableexit ~4.7s after a completed check

This could be chance, but it may point to the auto-updater poll or something on the same timer. I could not confirm a cause. Resource exhaustion is ruled out (see Environment).

Impact

Major degradation or frequent failure

Version or commit

0.0.42 (T3-Code-0.0.42-x86_64.AppImage, Electron 44.1.0 / Chrome 152.0.7977.65, AppImage last updated 2026-09-23, channel latest)

Environment

Arch-based Linux (Omarchy), kernel 7.2.5, Hyprland 0.56.2 (Wayland, --ozone-platform=wayland), AppImage run with --no-sandbox via gtk-launch / uwsm. 23 GiB RAM (≈14 GiB available, swap unused), root FS at 14% used. No OOM-killer or systemd-oomd kills in the journal. T3 Code peak memory per scope was ~0.9 GB for the affected sessions.

Logs or stack traces

shell
1# journalctl — 20:34 exit (nothing else logged in the preceding ~7 minutes except unrelated ACPI noise)
2Sep 28 20:34:01.574 systemd[1]: tmp-.mount_t3codecmzR5I.mount: Deactivated successfully.
3Sep 28 20:34:02 systemd-coredump: Process 503540 (t3code) terminated abnormally with signal 7/BUS # --type=renderer
4Sep 28 20:34:03 systemd-coredump: Process 503605 (t3code) terminated abnormally with signal 7/BUS # apps/server/dist/bin.mjs
5Sep 28 20:34:06 systemd-coredump: Process 503278 (t3code) terminated abnormally with signal 7/BUS # network.mojom.NetworkService
6Sep 28 20:34:06 systemd[1400]: app-com.t3tools.T3Code-503112.scope: Consumed 1min 16s CPU time over 16min 6s wall clock time, 886.3M memory peak.
7# main process 503112: no coredump entry
8
9# journalctl — 18:21 exit
10Sep 28 18:21:10.276 systemd[1]: tmp-.mount_t3codeq8iEut.mount: Deactivated successfully.
11Sep 28 18:24:23 systemd-coredump: Process 14109 (t3code) terminated abnormally with signal 7/BUS # apps/server/dist/bin.mjs
12Sep 28 18:29:14 systemd-coredump: Process 13881 (t3code) terminated abnormally with signal 7/BUS # network.mojom.NetworkService
13
14# journalctl — 17:25 exit (session that had been up ~3 days)
15Sep 28 17:25:09.651 systemd[1]: tmp-.mount_t3codeZ3Y2jw.mount: Deactivated successfully.
16Sep 28 17:25:57 systemd-coredump: Process 26173 (t3code) terminated abnormally with signal 7/BUS # apps/server/dist/bin.mjs
17Sep 28 17:26:00 systemd-coredump: Process 25844 (t3code) terminated abnormally with signal 7/BUS # network.mojom.NetworkService
18Sep 28 17:38:13 systemd-coredump: Process 25838 (t3code) terminated abnormally with signal 7/BUS # --type=gpu-process
19
20# coredumpctl info 503540 (renderer)
21Signal: 7 (BUS) si_code: BUS_ADRERR
22Command Line: /tmp/.mount_t3codecmzR5I/t3code --type=renderer ... --app-path=/tmp/.mount_t3codecmzR5I/resources/app.asar ...
23
24# desktop.trace.ndjson — last non-IPC spans of the 18:09 session
2518:17:08.855 -> 18:17:09.583 desktop.updates.checkForUpdates Success {reason: poll}
2618:17:09.583 desktop.updates.handleUpdateNotAvailable Success
2718:21:09.585 desktop.updates.handleCheckingForUpdate Success
28# (no handleUpdateNotAvailable, no checkForUpdates end, no lifecycle spans — trace for this run ends here)
29
30# desktop.trace.ndjson — lifecycle spans across all runs, for comparison
3109-28 17:39:04 desktop.lifecycle.windowAllClosed / beforeQuit / requestShutdownAndWait # normal close
3209-28 17:56:58 desktop.lifecycle.windowAllClosed # system shutdown
3309-29 09:27:31 desktop.lifecycle.windowAllClosed / beforeQuit / requestShutdownAndWait # normal close
34# runs started 09-28 18:09:08 and 20:17:59 have lifecycle.register and nothing else

The trace files are available if useful (~/.t3/userdata/logs/desktop.trace.ndjson*, server.trace.ndjson*). They're large, so I can share them privately after redacting.

Workaround

None confirmed. Relaunching works, and thread history survives in state.sqlite. Next time I'll run the AppImage from a terminal (ELECTRON_ENABLE_LOGGING=1 ... ; echo $?) to capture the main process's stderr and exit status, and I'll add it here.

Possible directions

  • Log the main process's exit path: process.on('exit') with the code, plus render-process-gone / child-process-gone, and route electron-updater's logger into the trace. Right now these exits leave nothing in the trace.
  • Check whether the auto-updater poll (or anything on the same 4-min timer) can make the main process exit or hard-crash on Linux AppImage.
  • Check why Crashpad writes no minidump for the main process in this case. That would suggest a SIGKILL or an explicit exit/_exit rather than a native crash.

Triage

The child SIGBUS dumps are fallout, not the crash. A type-2 AppImage unmounts /tmp/.mount_t3code* when the main process goes away, and every child still mapped from that mount then dies with BUS_ADRERR. No windowAllClosed / beforeQuit / requestShutdownAndWait span, no main-process coredump, and no Crashpad minidump means the main process left through exit / _exit / app.exit or SIGKILL, not through our quit path and not through a signal that core-dumps.

That is not the auto-updater install path. On 0.0.42, desktop.updates.configure sets autoDownload and autoInstallOnAppQuit to false before the 4-minute poll, and checkForUpdates only hits the feed. The only app.exit in the desktop main process is desktop.lifecycle.relaunch, and that runs requestShutdownAndWait first, which would show up in the trace. quitAndInstall is user-driven and emits before-quit-for-update before app.quit().

The poll timing is a weak lead. Completed spans are written to desktop.trace.ndjson in 1-second batches, and a span is not written until it ends, so a death inside an open checkForUpdates can look like "no span". The 18:21 exit is the one that really happened mid-check: handleCheckingForUpdate finished, the parent span never closed, and the mount was gone about 0.7s later. The 17:25 exit is different. handleUpdateNotAvailable had already completed, and the mount disappeared 4.7s later, which is long enough that a finished shutdown span would have been flushed. Nothing in our poller or in electron-updater's check path calls exit.

The signature matches Electron's Linux ozone shutdown when the Wayland or X connection drops (electron/electron#52603, which is in 44.1.0). That calls Browser::ExitWithCode / app.exit(0), which skips before-quit and will-quit and writes no minidump. A protocol error on this client alone would do it without the rest of the session dying. Not confirmed.

Nothing on main adds process exit / child-process-gone logging, and the Electron bump there (44.1.0 to 44.4.2) has no note that it stops this exit. The useful next capture is the one you already planned, from a terminal:

ELECTRON_ENABLE_LOGGING=1 <appimage> --no-sandbox --ozone-platform=wayland ; echo exit:$?

On the next silent exit, the exit code plus any libwayland: / wl_display / wayland_event_watcher line distinguishes app.exit(0) from a signal. Also note whether any other Wayland client died at the same moment.

Synced from GitHub

Another occurrence on 0.0.45 (2026-10-11, Hyprland/Wayland, Arch/Omarchy). Same signature, but this time the orphaned children survived for ~1h45m after the main process went away, which pins the main-process exit time quite precisely.

Timeline (local time, -03):

TimeEventSource
03:49:09.43 → 03:49:10.29checkForUpdates {reason: poll} → handleUpdateNotAvailable, both spans closed with Successdesktop.trace.ndjson
03:49:32.70Last span in desktop.trace.ndjson: routine 3 s desktop:get-local-environment-enabled / get-local-environment-bootstraps IPC polling, all Success. No before-quit / windowAllClosed / requestShutdownAndWait / relaunch span.desktop.trace.ndjson
03:49:34.60systemd[1]: tmp-.mount_t3codelAlsSm.mount: Deactivated successfully.system journal
03:49 → 05:34Server (apps/server/dist/bin.mjs --bootstrap-fd 3), t3-resource-monitor and the network-service utility process keep running with the mount gone; server.trace.ndjson keeps writing normally (terminal.pollSubprocessActivity etc.) up to 05:34:41.8server.trace.ndjson
05:34:42Server process SIGBUS BUS_ADRERR (presumably faulting in a page not already cached from the vanished squashfs)coredumpctl
05:34:44t3-resource-monitor SIGBUS BUS_ADRERRcoredumpctl
05:34:49Network-service utility (--utility-sub-type=network.mojom.NetworkService) SIGBUS BUS_ADRERRcoredumpctl

Other observations

  • No main-process coredump, no Crashpad minidump, no OOM kill, no suspend/resume, no update file change (t3code.AppImage unchanged since the 0.0.45 install on 10-05). SingletonLock was left behind in ~/.config/t3code.
  • Re: whether another Wayland client died at the same moment: no. Hyprland has been running continuously since 10-07 17:12; no other process exited or dumped core around 03:49, and the journal (system + user) has nothing between 03:49:01 and 03:50:59 apart from the mount deactivation. Hyprland debug logging wasn't enabled, so I can't rule out a protocol error on the T3 Code client itself.
  • The update poll finished ~22 s before the last main-process span, so per your 1 s flush note this one is not a death inside an open checkForUpdates.
  • This launch came from the desktop entry (gtk-launch), so unfortunately no ELECTRON_ENABLE_LOGGING stderr / exit code for this one. My terminal-logged instance ended on 10-05 when it was updated to 0.0.45 (clean rc 0 via quitAndInstall). I'll restart under the logging wrapper to capture the exit code on the next one.

A possibly separate point: when the main process vanishes, the server/utility children are not torn down and keep running orphaned until they touch an uncached page. It might be worth having the server exit when its bootstrap fd / parent goes away (e.g. PR_SET_PDEATHSIG or watching the bootstrap fd), so it fails fast instead of lingering in a half-dead state.

Synced from GitHub

Additional Linux x86_64 AppImage evidence from Fedora/KDE, collected with Codex assistance. This shares the child SIGBUS + AppImage unmount symptom, but is not a confirmed reproduction of the original silent-exit bug: windowAllClosed is present in this case, and the desktop was under memory pressure. Posting here to help distinguish the failure paths rather than opening a presumed duplicate.

Area / impact / reproduction

apps/desktop. The user reported applications crashing during the desktop session. One T3 Code incident is confirmed by two core dumps on 2026-10-17 at 22:46:04 CEST (20:46:04 UTC). There is no deterministic reproducer or confirmed user action immediately preceding the event. The T3 application scope had been running for approximately 41 minutes. Expected: continued operation, or a clean shutdown without crashing child processes. Actual: two T3 zygote processes terminated with SIGBUS and the AppImage mount was deactivated. Frequency and impact on persisted threads have not been established.

Version / environment

  • Installed launcher targets T3-Code-0.1.0-x86_64.AppImage; desktop metadata also says 0.1.0. The file's mtime predates the incident (2026-10-17 09:49 CEST). This identifies the configured installation, not an independently recovered version/commit from the crashed executable. Electron version was not verified.
  • Fedora 44, kernel 7.2.4-200.fc44.x86_64, KDE Plasma package plasma-workspace-6.7.5-1.fc44.x86_64, running kwin_wayland.
  • AMD Renoir / Radeon Vega GPU. T3's actual native Wayland versus XWayland backend has not been verified.
  • Launcher uses <install-dir>/T3-Code-0.1.0-x86_64.AppImage --no-sandbox %U.
  • System-reported RAM: 15,341 MiB; swap: 8 GiB zRAM. Other applications and development tools were running concurrently.

Timeline / relevant evidence

All times below are CEST, UTC+02:00, converted from the desktop trace's Unix timestamps where applicable.

TimeEvidence
22:41:48.371–22:41:49.046Last observed update poll: desktop.updates.checkForUpdates, with handleUpdateNotAvailable; successful.
22:45:18.597PreviewManager.closeAllPictureInPicture, success.
22:45:18.633PreviewManager.stopAllRecordings, success.
22:45:18.728–22:45:19.050desktop.lifecycle.windowAllClosed, success. This differs from the original report.
22:45:37KWin: The main thread was hanging temporarily!
22:45:48.967desktop.window.handleBackendNotReady, success; final record in the current desktop trace.
22:46:04Two T3 zygotes receive signal 7/BUS; AppImage mount deactivates in the same second. This does not establish subsecond causal ordering.
22:46:05Both core dumps recorded.
22:46:06Chrome emits a GLib assertion and its application scope/service ends. This is evidence of another application ending nearby, not proof of a Chrome crash or common cause.

Selected redacted local evidence:

text
1PID 1693415: Signal 7 (BUS)
2Command Line: /tmp/.mount_T3-CodcjhnHG/t3code --type=zygote --no-zygote-sandbox --no-sandbox
3Executable: /t3code
4
5PID 1693416: Signal 7 (BUS)
6Command Line: /tmp/.mount_T3-CodcjhnHG/t3code --type=zygote --no-sandbox
7Executable: /t3code
8
922:46:04 systemd: tmp-.mount_T3\x2dCodcjhnHG.mount: Deactivated successfully.
1022:46:04 systemd: app-com.t3tools.T3Code-1693399.scope:
11 Consumed 2min 31.304s CPU time over 41min 27.670s wall clock time,
12 1G memory peak, 5.9M memory swap peak.
1322:46:06 Chrome: GLib: g_main_context_pop_thread_default: assertion 'stack != NULL' failed

The coredump listing for the inspected three-hour interval contained these two T3 children, with no T3 main-process core. The inspected desktop traces contain windowAllClosed, but no observed beforeQuit or requestShutdownAndWait span for this exit. No main-process stderr/exit code was captured; Crashpad was not inspected.

Memory context and limits of the diagnosis

Measurements were taken around 23:21–23:25, roughly 35–39 minutes after the crash, not at crash time:

  • zRAM swap was effectively full (8 GiB logical data, approximately 3.8 GiB physical RAM after compression); available RAM was about 3.3 GiB.
  • /tmp is tmpfs and held about 4.1 GiB of files. Its exact resident/swapped split was not measured.
  • Other applications materially consumed memory, including ChatGPT/Codex and development tools; Discover alone had about 1.4 GiB in SwapPss. These are system context, not evidence of a T3 memory leak.
  • No OOM-killer kill or systemd-oomd event was found in the inspected three-hour journal window. That does not rule out memory-pressure effects.
  • Root filesystem had about 57 GiB free; /dev/shm was nearly empty at inspection time.

Workaround / open questions

No workaround has been tested. No data directories were reset or deleted. Raw traces and core dumps were not uploaded because they may contain private data; only relevant excerpts are included here.

Does the presence of windowAllClosed followed by delayed zygote SIGBUS warrant tracking this as a separate shutdown/child-lifetime issue? The mount/child failure resembles this issue, but the evidence currently does not establish a silent main-process exit, an updater fault, an OOM kill, or a GPU/Wayland root cause.

Synced from GitHub

Additional x86_64 datapoint with core-level detail — silent-exit path, not orderly shutdown

Posting here rather than opening a new issue because the signature matches this report: children of a T3 AppImage die with SIGBUS/BUS_ADRERR after the mount goes away, with no main-process core. (Cross-ref #24315, the orderly-shutdown variant on arm64.)

Version / environment: T3 Code 0.1.3-nightly.20261027.3748, Electron 44.9.3 / Chrome 152.0.7977.167, x86_64 AppImage, Arch-based Linux, Wayland/Hyprland.

What crashed: the network-service utility (--type=utility --utility-sub-type=network.mojom.NetworkService), thread Chrome_ChildIOT, SIGBUS, si_code=BUS_ADRERR.

Core findings

  • si_addr == RIP: the faulting address is the instruction pointer, i.e. an instruction-fetch fault, not a wild data access.
  • RIP is inside the executable's r-x LOAD segment (file offset ~0x342f000, size ~0x9f2d710), a code page of the AppImage's squashfs filesystem. Matches the GDB finding in #24315 on arm64.
  • Frames unresolved (release build); no third-party library in the crashed thread.

Trace evidence (silent exit)

The desktop trace's last span from the dying process is a routine desktop.ipc.* at T. There are no windowAllClosed / beforeQuit / requestShutdownAndWait spans and no relaunch span. The next spans are a new instance's desktop.startup starting ~6 s later. The desktop's local server stopped ~0.6 s before the SIGBUS.

Ordering

  • T: last main-process span (routine IPC)
  • T+~0.6 s: local server gone
  • T+~2 s: network service SIGBUS
  • +3 ms: mount unit deactivated
  • +24 ms: second mount unit deactivated
  • +4 s: new instance launched from the desktop entry

Mount teardown is not the first event; the main process was already gone. But the faulting page is a code page from the mount, consistent with the orphan-child mechanism above.

Update/mount churn (possibly the trigger)

The AppImage on disk had been replaced by the auto-updater ~3 h before this exit while the instance kept running from the then-current mount. The crashed process's environment (PATH and GSETTINGS_SCHEMA_DIR) still contained two AppImage mounts — the one it was executing from plus an earlier one — and both mount units were torn down within 30 ms of each other. That is the update/relaunch path leaving a process tree spanning two mounts (cf. closed #18790 about mount dirs piling up on PATH). Not proven as the cause of the main-process exit, but it is the state the crash happened in.

Ruled out: no OOM-killer/systemd-oomd kill, plenty of free memory, no btrfs/FUSE read errors, /tmp nearly empty. No main-process coredump and no Crashpad minidump (Crashpad dir contains only client_id).

Impact: the desktop disappeared mid-session and was relaunched ~2 s later; no data loss observed (state reopened fine, server came back on the same build/port).

No core uploaded (verbatim memory image). Happy to pull specific offsets or trace excerpts if useful.

Synced from GitHub

Another x86_64 datapoint on stable v0.1.7: silent-exit path, child SIGBUS

Version / environment: T3 Code v0.1.7 (stable, AppImage unchanged since 2026-11-05), x86_64, Arch-based Omarchy (kernel 7.2.15), Hyprland/Wayland, update channel latest.

What crashed: a SnapShotAccessibilityWorker.cjs read helper (/tmp/.mount_T3-Cod*/t3code …/dist-electron/snapShot/SnapShotAccessibilityWorker.cjs read), SIGBUS BUS_ADRERR. It was already in libc exit(); frame #0 had no backing file (n/a + 0x0), so the code page it needed was gone.

Timeline (2026-11-08, local time):

  • up to 17:38:19: desktop.trace.ndjson shows only routine spans (resolvePrimaryLabel every 3 s, getSystemIdleState)
  • no desktop.lifecycle.beforeQuit, processSignal, relaunch or requestShutdownAndWait spans
  • 17:38:21: tmp-.mount_T3\x2dCod….mount: Deactivated successfully; same second the worker dumps core with SIGBUS
  • 17:38:25: desktop.startup (new mount)

Ruled out: no main-process core, no Crashpad minidump, no OOM kill, no AppImage update.

Recurrence: the same child-SIGBUS-after-unmount pattern happened four times between 2026-11-06 and 2026-11-08 (backend bin.mjs, an expo-device-hub child, t3-resource-monitor and this worker).

The user confirms they did not close, quit or restart the app at that moment: the window simply disappeared.


Produced by Claude Code (Claude Opus 5.5) via T3 Code triage.