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.
omarchy-snapshot: a failed sudo is reported as "No Snapper configs found", and the suggested fix overwrites a working /etc/snapper/configs/root
Reported by ericziko · filed Sep 6, 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
Summary
When the sudo call inside omarchy-snapshot create fails, the script reports "No Snapper configs found" and tells the user to run install/config/snapper.sh — even when a perfectly good /etc/snapper/configs/root exists.
Following that advice runs install -m 0644 "$template" /etc/snapper/configs/root, which overwrites the existing config and disables snapper-timeline.timer. So a misdiagnosed failure leads the user to silently revert their own snapper configuration.
This matters most during omarchy update, which calls omarchy-snapshot create — precisely when you most want a snapshot, and precisely when the user is most likely to act on the suggested fix.
Reproduction
Any condition that makes sudo fail reproduces it. Two realistic ones:
1. No controlling terminal (a script, a systemd unit, an SSH command without a pty, or an agent):
$ omarchy snapshot create
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
sudo: a password is required
No Snapper configs found, so no snapshot was created.
Configure Snapper with: sudo bash -euo pipefail "/usr/share/omarchy/install/config/snapper.sh"
$ echo $?
12. In a normal terminal: press Ctrl-C at the password prompt, or mistype the password three times. Same output.
But a config plainly exists:
$ snapper list-configs
Config │ Subvolume
───────┼──────────
root │ /
$ ls -l /etc/snapper/configs/root
-rw-r--r-- 1 root root 217 Aug 30 21:48 /etc/snapper/configs/rootRoot cause
omarchy-snapshot, in the create branch:
# Get existing snapper config names from CSV output
mapfile -t CONFIGS < <(sudo snapper --csvout list-configs | awk -F, 'NR>1 {print $1}')
# Snapper installed but unconfigured snapshots nothing. Staying quiet here
# reads as a successful snapshot, so the next update looks recoverable when
# nothing has ever been captured.
if (( ${#CONFIGS[@]} == 0 )); then
echo -e "\e[33mNo Snapper configs found, so no snapshot was created.\e[0m" >&2
echo "Configure Snapper with: sudo bash -euo pipefail \"$OMARCHY_PATH/install/config/snapper.sh\"" >&2
exit 1
fisudo failing produces empty stdout, so CONFIGS is empty — indistinguishable from "snapper has no configs". The script reports the latter.
set -e does not catch it: the failing command is inside a process substitution feeding mapfile, so its exit status never reaches the shell's error check. Confirmed directly:
$ out="$(sudo -n snapper --csvout list-configs 2>/dev/null | awk -F, 'NR>1 {print $1}')"
$ echo "captured: [$out] length=${#out}"
captured: [] length=0The comment immediately above the check shows the failure mode was already on your mind — the concern about staying quiet is exactly right. The check just conflates two different causes of an empty list.
Why the suggested remedy is harmful
install/config/snapper.sh does:
install -m 0644 "$template" "$SNAPPER_CONFIG_PATH" # unconditional overwrite
...
systemctl disable --now snapper-timeline.timerA user who had tuned NUMBER_LIMIT, or deliberately enabled timeline snapshots, loses those settings — while believing they are fixing an unrelated problem. The advice is sound for a genuinely unconfigured system and wrong for this one, and the user cannot tell the difference from the message.
Suggested fix
Separate "the query failed" from "the query succeeded and returned nothing":
# Capture separately so sudo/snapper failure is distinguishable from an empty list.
if ! configs_csv="$(sudo snapper --csvout list-configs 2>&1)"; then
echo -e "\e[31mCould not query Snapper (is sudo available?).\e[0m" >&2
printf '%s\n' "$configs_csv" >&2
exit 1
fi
mapfile -t CONFIGS < <(printf '%s\n' "$configs_csv" | awk -F, 'NR>1 {print $1}')
if (( ${#CONFIGS[@]} == 0 )); then
echo -e "\e[33mNo Snapper configs found, so no snapshot was created.\e[0m" >&2
echo "Configure Snapper with: sudo bash -euo pipefail \"$OMARCHY_PATH/install/config/snapper.sh\"" >&2
exit 1
fiThe "configure Snapper" hint then only appears when snapper really is unconfigured.
Happy to open a PR if that shape looks right.
System details
| Omarchy | 4.0.2-1 |
| Kernel | 7.1.9-arch1-2 |
| CPU / GPU | AMD Ryzen 7 8745HS w/ Radeon 780M |
| Model | GEEKOM AX8 MAX |
| snapper | 0.13.1-3 |
| limine-snapper-sync | 1.31.0-1 |
Note: contributing-style diagnostics via omarchy debug --no-sudo --print were not available — omarchy debug is not a command in 4.0.2-1 (Unknown Omarchy command), so the above was gathered manually.
View raw text
## Summary
When the `sudo` call inside `omarchy-snapshot create` fails, the script reports **"No Snapper configs found"** and tells the user to run `install/config/snapper.sh` — even when a perfectly good `/etc/snapper/configs/root` exists.
Following that advice runs `install -m 0644 "$template" /etc/snapper/configs/root`, which **overwrites the existing config** and disables `snapper-timeline.timer`. So a misdiagnosed failure leads the user to silently revert their own snapper configuration.
This matters most during `omarchy update`, which calls `omarchy-snapshot create` — precisely when you most want a snapshot, and precisely when the user is most likely to act on the suggested fix.
## Reproduction
Any condition that makes `sudo` fail reproduces it. Two realistic ones:
**1. No controlling terminal** (a script, a systemd unit, an SSH command without a pty, or an agent):
```console
$ omarchy snapshot create
sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
sudo: a password is required
No Snapper configs found, so no snapshot was created.
Configure Snapper with: sudo bash -euo pipefail "/usr/share/omarchy/install/config/snapper.sh"
$ echo $?
1
```
**2. In a normal terminal:** press Ctrl-C at the password prompt, or mistype the password three times. Same output.
But a config plainly exists:
```console
$ snapper list-configs
Config │ Subvolume
───────┼──────────
root │ /
$ ls -l /etc/snapper/configs/root
-rw-r--r-- 1 root root 217 Aug 30 21:48 /etc/snapper/configs/root
```
## Root cause
`omarchy-snapshot`, in the `create` branch:
```bash
# Get existing snapper config names from CSV output
mapfile -t CONFIGS < <(sudo snapper --csvout list-configs | awk -F, 'NR>1 {print $1}')
# Snapper installed but unconfigured snapshots nothing. Staying quiet here
# reads as a successful snapshot, so the next update looks recoverable when
# nothing has ever been captured.
if (( ${#CONFIGS[@]} == 0 )); then
echo -e "\e[33mNo Snapper configs found, so no snapshot was created.\e[0m" >&2
echo "Configure Snapper with: sudo bash -euo pipefail \"$OMARCHY_PATH/install/config/snapper.sh\"" >&2
exit 1
fi
```
`sudo` failing produces empty stdout, so `CONFIGS` is empty — indistinguishable from "snapper has no configs". The script reports the latter.
`set -e` does not catch it: the failing command is inside a process substitution feeding `mapfile`, so its exit status never reaches the shell's error check. Confirmed directly:
```console
$ out="$(sudo -n snapper --csvout list-configs 2>/dev/null | awk -F, 'NR>1 {print $1}')"
$ echo "captured: [$out] length=${#out}"
captured: [] length=0
```
The comment immediately above the check shows the failure mode was already on your mind — the concern about staying quiet is exactly right. The check just conflates two different causes of an empty list.
## Why the suggested remedy is harmful
`install/config/snapper.sh` does:
```bash
install -m 0644 "$template" "$SNAPPER_CONFIG_PATH" # unconditional overwrite
...
systemctl disable --now snapper-timeline.timer
```
A user who had tuned `NUMBER_LIMIT`, or deliberately enabled timeline snapshots, loses those settings — while believing they are fixing an unrelated problem. The advice is sound for a genuinely unconfigured system and wrong for this one, and the user cannot tell the difference from the message.
## Suggested fix
Separate "the query failed" from "the query succeeded and returned nothing":
```bash
# Capture separately so sudo/snapper failure is distinguishable from an empty list.
if ! configs_csv="$(sudo snapper --csvout list-configs 2>&1)"; then
echo -e "\e[31mCould not query Snapper (is sudo available?).\e[0m" >&2
printf '%s\n' "$configs_csv" >&2
exit 1
fi
mapfile -t CONFIGS < <(printf '%s\n' "$configs_csv" | awk -F, 'NR>1 {print $1}')
if (( ${#CONFIGS[@]} == 0 )); then
echo -e "\e[33mNo Snapper configs found, so no snapshot was created.\e[0m" >&2
echo "Configure Snapper with: sudo bash -euo pipefail \"$OMARCHY_PATH/install/config/snapper.sh\"" >&2
exit 1
fi
```
The "configure Snapper" hint then only appears when snapper really is unconfigured.
Happy to open a PR if that shape looks right.
## System details
| | |
|---|---|
| Omarchy | `4.0.2-1` |
| Kernel | `7.1.9-arch1-2` |
| CPU / GPU | AMD Ryzen 7 8745HS w/ Radeon 780M |
| Model | GEEKOM AX8 MAX |
| snapper | `0.13.1-3` |
| limine-snapper-sync | `1.31.0-1` |
Note: `contributing`-style diagnostics via `omarchy debug --no-sudo --print` were not available — `omarchy debug` is not a command in 4.0.2-1 (`Unknown Omarchy command`), so the above was gathered manually.
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 10:55 UTC