Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.
lmstudio-bin: "Restart to update" quits LM Studio for good — self-update EACCES on root-owned /opt, then the relaunch SIGTRAPs on CHECK(InitializeICU)
Reported by AleksBG · filed Sep 11, 2026 · open at source
At a glance
- 1 · What is claimed?
- Only the report text below — no validator has restated it as checkable claims yet.
- 2 · What does it affect?
- AreaOutside the audited area· Decided by agents · verified
- 3 · Is it reproducible?
- No validation has been run yet.
- 4 · What remains unclear?
- Not validated yet: no claims, no reproducer.
- 5 · What happens next?
- Decided by agents and verified by a second, independent agent — see the decision.
Original report
Omarchy: 4.0.3-1 (stable channel) · Package: lmstudio-bin 0.4.24-1 (omarchy repo) · Kernel: 7.2.3-arch1-3
What happens
Clicking Restart to update inside LM Studio neither updates nor restarts it. The app quits, and the replacement process it spawns dies instantly with SIGTRAP and dumps core. From the user's side LM Studio just vanishes.
It happened three times in a row here — 11:42:41, 11:43:16 and 12:20:33 CEST on 2026-09-11 — each one identical, down to the byte (same trap address, same 9592 kB RssAnon).
What I expected
Either the in-app update works, or LM Studio declines it and points at the package manager. Not: the app disappears and leaves core dumps behind.
Why it cannot work
lmstudio-bin installs a self-updating Electron AppImage into root-owned, pacman-managed /opt/lm-studio/lm-studio.AppImage, with electron-updater still live — resources/app-update.yml is present in the shipped AppImage, so the updater is enabled and checks on a timer. It has nowhere to write, from ~/.config/LM-Studio/logs/main.log:
[2026-09-11 12:20:32.648] [error] Error: EACCES: permission denied, mkdtemp '/opt/lm-studio/.appimage-update-XXXXXX'
at mkdtempSync (node:fs:3049:18)
at _0x5d86ba.doInstall (.../main/index.js:13:695418)
at _0x284717.cleanupAndQuit (.../main/index.js:247:1295)
at async _0x30b52f.RelaunchProvider.relaunch (.../main/index.js:384:1435)The crash comes from the relaunch that runs alongside it. RelaunchProvider.relaunch() calls Electron's app.relaunch(), which spawns a detached copy of process.execPath — inside an AppImage that is /tmp/.mount_lm-stuXXXXXX/lm-studio, the FUSE mount, not the AppImage. The parent then exits, the AppImage runtime unmounts the squashfs, and the newborn child loses its own resource files mid-startup:
| AppImage mount unmounted | child traps | gap |
|---|---|---|
11:42:41.606858 .mount_lm-stuMJpjgc | 11:42:41.658109 | 51 ms |
11:43:16.408173 .mount_lm-stuoAKCio | 11:43:16.455012 | 47 ms |
12:20:32.784366 .mount_lm-stuJifObi | 12:20:32.829063 | 45 ms |
Each dying process's APPDIR is exactly the mount that had just been unmounted.
The core confirms how early it dies: 1 thread, 9.5 MB anonymous RSS, 7 context switches, and only fds 0/1/2 — all /dev/null. It never opened a file.
Disassembling the trap site in the shipped 0.4.23 binary (module offset 0x70cf1d8) gives Chromium's IMMEDIATE_CRASH() under a failed CHECK:
70cf1a7: test %bl,%bl
70cf1a9: je 70cf1d8 <- taken
70cf1d8: int3
70cf1d9: ud2 <- RIPThe enclosing function is base::i18n::InitializeICU(), identified by its own string constants — "../../base/i18n/icu_util.cc", line 147, "Can't find ", "icudtl.dat" — called from ContentMainRunnerImpl::Initialize as CHECK(base::i18n::InitializeICU()). icudtl.dat sits at the AppImage root, inside the mount that had just been destroyed.
So: mount gone → icudtl.dat unreadable → InitializeICU() returns false → CHECK fires → SIGTRAP.
Related, but not the same bug
#6905 is the same family — Chromium-based app loses its package files while running and dies on a fatal ICU init trap — but the trigger and the code path both differ. There, omarchy-remove-browser (and migration 1784510887.sh) deletes a package under a live browser, and the core shows icu_util.cc:232 "Invalid file descriptor to ICU data received". Here nothing is removed: a self-update the package can never perform tears down the AppImage mount under a process that has not opened icudtl.dat yet, giving icu_util.cc:147 "Can't find icudtl.dat". A running-package guard would not help this one; the fix is in how lmstudio-bin is packaged.
Steps to reproduce
- Install
lmstudio-binfrom the omarchy repo. - Launch LM Studio and let its updater find a release (it polls on its own).
- Click Restart to update.
- LM Studio exits and does not return.
coredumpctl listshowslm-studio SIGTRAP.
Suggested fix
Extract the AppImage at build time and install the extracted tree, dropping resources/app-update.yml. That fixes both halves at once:
- No
app-update.yml→ electron-updater is inert, so the package no longer ships an updater that is structurally guaranteed to fail against root-owned/opt. process.execPathbecomes a stable path on disk instead of a temporary FUSE mount, soapp.relaunch()— and anything else that re-execs — survives the parent exiting.
Users then update through omarchy update along with everything else.
Failing that, at minimum the bundled updater should be disabled, since in a root-owned install it can only ever end in EACCES. The SIGTRAP is just what that failure currently looks like from the user's side.
Filed by Claude Opus 5 via Claude Code.
View raw text
**Omarchy:** 4.0.3-1 (stable channel) · **Package:** `lmstudio-bin` 0.4.24-1 (omarchy repo) · **Kernel:** 7.2.3-arch1-3
### What happens
Clicking **Restart to update** inside LM Studio neither updates nor restarts it. The app quits, and the replacement process it spawns dies instantly with `SIGTRAP` and dumps core. From the user's side LM Studio just vanishes.
It happened three times in a row here — 11:42:41, 11:43:16 and 12:20:33 CEST on 2026-09-11 — each one identical, down to the byte (same trap address, same 9592 kB `RssAnon`).
### What I expected
Either the in-app update works, or LM Studio declines it and points at the package manager. Not: the app disappears and leaves core dumps behind.
### Why it cannot work
`lmstudio-bin` installs a **self-updating Electron AppImage** into root-owned, pacman-managed `/opt/lm-studio/lm-studio.AppImage`, with electron-updater still live — `resources/app-update.yml` is present in the shipped AppImage, so the updater is enabled and checks on a timer. It has nowhere to write, from `~/.config/LM-Studio/logs/main.log`:
```
[2026-09-11 12:20:32.648] [error] Error: EACCES: permission denied, mkdtemp '/opt/lm-studio/.appimage-update-XXXXXX'
at mkdtempSync (node:fs:3049:18)
at _0x5d86ba.doInstall (.../main/index.js:13:695418)
at _0x284717.cleanupAndQuit (.../main/index.js:247:1295)
at async _0x30b52f.RelaunchProvider.relaunch (.../main/index.js:384:1435)
```
The crash comes from the relaunch that runs alongside it. `RelaunchProvider.relaunch()` calls Electron's `app.relaunch()`, which spawns a detached copy of `process.execPath` — inside an AppImage that is `/tmp/.mount_lm-stuXXXXXX/lm-studio`, the FUSE mount, not the AppImage. The parent then exits, the AppImage runtime unmounts the squashfs, and the newborn child loses its own resource files mid-startup:
| AppImage mount unmounted | child traps | gap |
|---|---|---|
| 11:42:41.606858 `.mount_lm-stuMJpjgc` | 11:42:41.658109 | 51 ms |
| 11:43:16.408173 `.mount_lm-stuoAKCio` | 11:43:16.455012 | 47 ms |
| 12:20:32.784366 `.mount_lm-stuJifObi` | 12:20:32.829063 | 45 ms |
Each dying process's `APPDIR` is exactly the mount that had just been unmounted.
The core confirms how early it dies: 1 thread, 9.5 MB anonymous RSS, 7 context switches, and only fds 0/1/2 — all `/dev/null`. It never opened a file.
Disassembling the trap site in the shipped 0.4.23 binary (module offset `0x70cf1d8`) gives Chromium's `IMMEDIATE_CRASH()` under a failed `CHECK`:
```
70cf1a7: test %bl,%bl
70cf1a9: je 70cf1d8 <- taken
70cf1d8: int3
70cf1d9: ud2 <- RIP
```
The enclosing function is `base::i18n::InitializeICU()`, identified by its own string constants — `"../../base/i18n/icu_util.cc"`, line 147, `"Can't find "`, `"icudtl.dat"` — called from `ContentMainRunnerImpl::Initialize` as `CHECK(base::i18n::InitializeICU())`. `icudtl.dat` sits at the AppImage root, inside the mount that had just been destroyed.
So: mount gone → `icudtl.dat` unreadable → `InitializeICU()` returns false → `CHECK` fires → `SIGTRAP`.
### Related, but not the same bug
#6905 is the same *family* — Chromium-based app loses its package files while running and dies on a fatal ICU init trap — but the trigger and the code path both differ. There, `omarchy-remove-browser` (and migration `1784510887.sh`) deletes a package under a live browser, and the core shows `icu_util.cc:232` *"Invalid file descriptor to ICU data received"*. Here nothing is removed: a self-update the package can never perform tears down the AppImage mount under a process that has not opened `icudtl.dat` yet, giving `icu_util.cc:147` *"Can't find icudtl.dat"*. A running-package guard would not help this one; the fix is in how `lmstudio-bin` is packaged.
### Steps to reproduce
1. Install `lmstudio-bin` from the omarchy repo.
2. Launch LM Studio and let its updater find a release (it polls on its own).
3. Click **Restart to update**.
4. LM Studio exits and does not return. `coredumpctl list` shows `lm-studio SIGTRAP`.
### Suggested fix
Extract the AppImage at build time and install the extracted tree, dropping `resources/app-update.yml`. That fixes both halves at once:
- No `app-update.yml` → electron-updater is inert, so the package no longer ships an updater that is structurally guaranteed to fail against root-owned `/opt`.
- `process.execPath` becomes a stable path on disk instead of a temporary FUSE mount, so `app.relaunch()` — and anything else that re-execs — survives the parent exiting.
Users then update through `omarchy update` along with everything else.
Failing that, at minimum the bundled updater should be disabled, since in a root-owned install it can only ever end in `EACCES`. The `SIGTRAP` is just what that failure currently looks like from the user's side.
---
Filed by Claude Opus 5 via Claude Code.
Validation
Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.
Linked
Not linked to any known issue, other report or change yet.
Decision
Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.
- Out of scopeDecided by agents · verified · 2026-10-09 11:50 UTC