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.
btrfs-overlayfs is enabled by default, which makes snapshot rollback impossible: limine-snapper-sync refuses to start inside every snapshot boot
Reported by Cloud-Ops-Dev · filed Aug 24, 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
What's wrong?
btrfs-overlayfs and limine-snapper-sync are mutually exclusive, and Omarchy enables the first by default. The result is that snapshot rollback cannot work on a stock Omarchy install — omarchy-snapshot restore walks straight into it.
This is the same root cause as #6634, but a different and much more serious consequence. #6634 reports the overlay breaking systemd-remount-fs (failed unit, red splash). Nobody has reported that it also makes the restore path impossible, which matters far more: the recovery mechanism is installed, enabled, and advertised in the boot menu, so users reasonably believe they have a rollback when they have none. You find out at the worst possible moment.
The conflict
limine-mkinitcpio-hook ships /usr/lib/initcpio/hooks/btrfs-overlayfs. Its run_latehook fires when all three hold:
/new_rootis btrfs- its SOURCE path contains
/snapshot - the subvolume is
ro=true
Every snapper snapshot is ro=true, so every snapshot boot gets an overlayfs mounted over /.
/usr/lib/limine/limine-snapper-sync (from the same upstream project family) requires / itself to be btrfs and bails at startup otherwise. Under the overlay, btrfs property get / ro returns ERROR: object is not a btrfs object: /.
So the entire chain dies before it starts:
omarchy-snapshot restore
-> sudo limine-snapper-restore
-> limine-snapper-sync --restore --no-mutex
-> /usr/lib/limine/limine-snapper-sync
"You are not in Btrfs, the tool does not update anything!"The check runs before argument parsing, so even `--help` prints only that line and exits.
Upstream states the assumption plainly in its own CHANGELOG (1.9.5): "Booted from a read-only Btrfs snapshot without overlayfs." The two features were never designed to coexist. Omarchy enables the overlay in /etc/mkinitcpio.conf.d/omarchy_hooks.conf and separately wires omarchy-snapshot restore to the tool that the overlay disables.
Steps to reproduce
Stock Omarchy 4.x on btrfs with snapper + Limine.
sudo snapper -c root create -d testsudo limine-snapper-sync(refresh the boot menu)- Reboot, pick the snapshot from Limine's Snapshots submenu
- Observe:
findmnt -no FSTYPE / # overlay (expected: btrfs)
sudo btrfs property get / ro # ERROR: object is not a btrfs object: /
sudo limine-snapper-sync --restore # You are not in Btrfs, the tool does not update anything!
sudo omarchy-snapshot restore # same, via limine-snapper-restoreVerified on Omarchy 4.0.0 (quattro), kernel 7.1.8-arch1-3, limine-snapper-sync 1.31.0-1, limine-mkinitcpio-hook 1.37.1-1, btrfs, no LUKS, Limine UKI.
Ruled out
Both of the tool's documented escapes still fail — the /-is-btrfs check precedes them:
- pre-mounting the btrfs top level (
mount -t btrfs -o subvol=/ /dev/… /mnt/btrfs) - setting
ROOT_SUBVOLUME_PATH="@"in/etc/default/limine(the binary's own option; cf. its string "No ROOT_SUBVOLUME_PATH. Please set ROOT_SUBVOLUME_PATH in /etc/default/limine")
limine-snapper-sync 1.31.0 is the latest release, so there is no version to upgrade into.
There is also a catch-22 that rules out the obvious workaround of "just restore from the normal boot": the snapshot to restore is identified by a regex on /proc/cmdline (subvol=.*?/([0-9]+)/snapshot), which only matches when you are booted into a snapshot. Booted normally, / is btrfs and the tool runs — but there is no snapshot for it to act on.
Fix
The cleanest fix is to stop enabling the overlay by default, since it silently trades away rollback — which is the entire point of shipping snapper + Limine. A read-only snapshot boot is also inherently safer for recovery: it cannot dirty the snapshot it is about to restore from.
If the overlay is worth keeping for its writable-snapshot-boot convenience, then omarchy-snapshot restore should at minimum detect the overlay and say so, instead of surfacing "You are not in Btrfs" from a nested helper.
Workaround
A drop-in that sorts after omarchy_hooks.conf filters the hook out. It must sort after, because omarchy_hooks.conf assigns HOOKS=(...) outright (cf. #6876); mkinitcpio 41.1 collects /etc/mkinitcpio.conf.d/*.conf via sort -zVu, so a zz- prefix lands last. This touches no package-owned file, so unlike patching the hook body it needs no NoUpgrade pacman hook to survive updates.
/etc/mkinitcpio.conf.d/zz-no-btrfs-overlayfs.conf:
_hooks=()
for _h in "${HOOKS[@]}"; do
[[ $_h == "btrfs-overlayfs" ]] || _hooks+=("$_h")
done
HOOKS=("${_hooks[@]}")
unset _hooks _hThen sudo limine-mkinitcpio — not mkinitcpio -P, which is a silent no-op on Omarchy because /etc/mkinitcpio.d/ is empty (UKI, not preset images).
Verified end to end after applying: snapshot boot lands on findmnt -no FSTYPE / = btrfs, btrfs property get / ro = ro=true, and limine-snapper-sync --restore completes normally — mounts the btrfs top level, swaps @, re-parents the child subvolumes and preserves the previous @ as a new snapshot.
One trap for anyone testing this
Snapshot boot entries are pinned to the UKI that was current when the snapshot was taken (limine_history/snapshots.json). Rebuilding the UKI does not retrofit existing entries — they keep booting the old initramfs, overlay hook included. After applying the workaround you must take a new snapshot, or you will test the fix against an image that does not contain it and conclude it failed.
Related
- #6634 — same root cause, reported for the
systemd-remount-fs/ red-splash symptom - #6633 — the companion fstab layer
- #6876 —
omarchy_hooks.confassignsHOOKSrather than extending it (why the drop-in must sort last)
View raw text
### What's wrong?
`btrfs-overlayfs` and `limine-snapper-sync` are mutually exclusive, and Omarchy enables the first by default. The result is that **snapshot rollback cannot work on a stock Omarchy install** — `omarchy-snapshot restore` walks straight into it.
This is the same root cause as #6634, but a different and much more serious consequence. #6634 reports the overlay breaking `systemd-remount-fs` (failed unit, red splash). Nobody has reported that it also makes the restore path impossible, which matters far more: the recovery mechanism is installed, enabled, and advertised in the boot menu, so users reasonably believe they have a rollback when they have none. You find out at the worst possible moment.
### The conflict
`limine-mkinitcpio-hook` ships `/usr/lib/initcpio/hooks/btrfs-overlayfs`. Its `run_latehook` fires when all three hold:
1. `/new_root` is btrfs
2. its SOURCE path contains `/snapshot`
3. the subvolume is `ro=true`
Every snapper snapshot is `ro=true`, so **every** snapshot boot gets an overlayfs mounted over `/`.
`/usr/lib/limine/limine-snapper-sync` (from the same upstream project family) requires `/` *itself* to be btrfs and bails at startup otherwise. Under the overlay, `btrfs property get / ro` returns `ERROR: object is not a btrfs object: /`.
So the entire chain dies before it starts:
```
omarchy-snapshot restore
-> sudo limine-snapper-restore
-> limine-snapper-sync --restore --no-mutex
-> /usr/lib/limine/limine-snapper-sync
"You are not in Btrfs, the tool does not update anything!"
```
The check runs before argument parsing, so **even `--help` prints only that line and exits.**
Upstream states the assumption plainly in its own CHANGELOG (1.9.5): *"Booted from a read-only Btrfs snapshot **without overlayfs**."* The two features were never designed to coexist. Omarchy enables the overlay in `/etc/mkinitcpio.conf.d/omarchy_hooks.conf` and separately wires `omarchy-snapshot restore` to the tool that the overlay disables.
### Steps to reproduce
Stock Omarchy 4.x on btrfs with snapper + Limine.
1. `sudo snapper -c root create -d test`
2. `sudo limine-snapper-sync` (refresh the boot menu)
3. Reboot, pick the snapshot from Limine's Snapshots submenu
4. Observe:
```bash
findmnt -no FSTYPE / # overlay (expected: btrfs)
sudo btrfs property get / ro # ERROR: object is not a btrfs object: /
sudo limine-snapper-sync --restore # You are not in Btrfs, the tool does not update anything!
sudo omarchy-snapshot restore # same, via limine-snapper-restore
```
Verified on Omarchy 4.0.0 (quattro), kernel 7.1.8-arch1-3, `limine-snapper-sync` 1.31.0-1, `limine-mkinitcpio-hook` 1.37.1-1, btrfs, no LUKS, Limine UKI.
### Ruled out
Both of the tool's documented escapes still fail — the `/`-is-btrfs check precedes them:
- pre-mounting the btrfs top level (`mount -t btrfs -o subvol=/ /dev/… /mnt/btrfs`)
- setting `ROOT_SUBVOLUME_PATH="@"` in `/etc/default/limine` (the binary's own option; cf. its string *"No ROOT_SUBVOLUME_PATH. Please set ROOT_SUBVOLUME_PATH in /etc/default/limine"*)
`limine-snapper-sync` 1.31.0 is the latest release, so there is no version to upgrade into.
There is also a catch-22 that rules out the obvious workaround of "just restore from the normal boot": the snapshot to restore is identified by a regex on `/proc/cmdline` (`subvol=.*?/([0-9]+)/snapshot`), which only matches when you are booted *into* a snapshot. Booted normally, `/` is btrfs and the tool runs — but there is no snapshot for it to act on.
### Fix
The cleanest fix is to stop enabling the overlay by default, since it silently trades away rollback — which is the entire point of shipping snapper + Limine. A read-only snapshot boot is also inherently safer for recovery: it cannot dirty the snapshot it is about to restore from.
If the overlay is worth keeping for its writable-snapshot-boot convenience, then `omarchy-snapshot restore` should at minimum detect the overlay and say so, instead of surfacing "You are not in Btrfs" from a nested helper.
### Workaround
A drop-in that sorts after `omarchy_hooks.conf` filters the hook out. It must sort *after*, because `omarchy_hooks.conf` assigns `HOOKS=(...)` outright (cf. #6876); `mkinitcpio` 41.1 collects `/etc/mkinitcpio.conf.d/*.conf` via `sort -zVu`, so a `zz-` prefix lands last. This touches no package-owned file, so unlike patching the hook body it needs no `NoUpgrade` pacman hook to survive updates.
`/etc/mkinitcpio.conf.d/zz-no-btrfs-overlayfs.conf`:
```bash
_hooks=()
for _h in "${HOOKS[@]}"; do
[[ $_h == "btrfs-overlayfs" ]] || _hooks+=("$_h")
done
HOOKS=("${_hooks[@]}")
unset _hooks _h
```
Then `sudo limine-mkinitcpio` — **not** `mkinitcpio -P`, which is a silent no-op on Omarchy because `/etc/mkinitcpio.d/` is empty (UKI, not preset images).
Verified end to end after applying: snapshot boot lands on `findmnt -no FSTYPE /` = `btrfs`, `btrfs property get / ro` = `ro=true`, and `limine-snapper-sync --restore` completes normally — mounts the btrfs top level, swaps `@`, re-parents the child subvolumes and preserves the previous `@` as a new snapshot.
### One trap for anyone testing this
Snapshot boot entries are pinned to the UKI that was current when the snapshot was **taken** (`limine_history/snapshots.json`). Rebuilding the UKI does not retrofit existing entries — they keep booting the old initramfs, overlay hook included. After applying the workaround you must take a **new** snapshot, or you will test the fix against an image that does not contain it and conclude it failed.
### Related
- #6634 — same root cause, reported for the `systemd-remount-fs` / red-splash symptom
- #6633 — the companion fstab layer
- #6876 — `omarchy_hooks.conf` assigns `HOOKS` rather than extending it (why the drop-in must sort last)
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 08:38 UTC