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 theme set reports success when post-theme hooks fail (run_parallel discards wait status)
Reported by Brams-s · filed Sep 7, 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 happened
omarchy theme set reports success even when its post-theme hooks fail. run_parallel (bin/omarchy-theme-set:33-45) waits on each hook and throws the status away:
for pid in "${pids[@]}"; do
wait "$pid"
doneThere is no set -e and no trap in the script, so nothing else catches it either. All fourteen entries in post_theme_commands — browser, vscode, obsidian, tmux, gnome, keyboard, the restart-* hooks — are unconditionally treated as having worked.
Reproducing with the function verbatim:
run_parallel() {
local pid
local pids=()
for command in "$@"; do
bash -lc "$command" &
pids+=("$!")
done
for pid in "${pids[@]}"; do
wait "$pid"
done
}
run_parallel "true" "exit 42" "nonexistent-command-xyz" "true"
echo "run_parallel returned: $?"bash: line 1: nonexistent-command-xyz: command not found
run_parallel returned: 0Why it stays invisible
The exit status is discarded here, and on the normal interactive path the hook's stderr is discarded too — shell/plugins/background/Background.qml:119:
command: ["bash", "-c", "theme=$(omarchy-theme-switcher); [[ -n $theme ]] && omarchy-theme-set \"$theme\" >/dev/null 2>&1 &"]So when a theme is changed from the picker, a broken hook produces no exit code, no message, and no notification. Nothing distinguishes it from a clean run, and the next theme change fails identically.
How I hit it
On this machine omarchy-theme-set-browser had been failing on every theme change for 17 days and I never saw it. It exits 1 with:
Error accessing /usr/bin/omarchy-theme-set-browser-policy: No such file or directoryomarchy-theme-set-browser-policy re-execs its own packaged path (correctly — etc/sudoers.d/omarchy-theme-browser names /usr/bin/omarchy-theme-set-browser-policy, so the rule only matches from there), and on this install that path did not exist. The visible symptom was unrelated-looking: Chromium was stuck showing the BrowserThemeColor of a theme I had stopped using, because /etc/chromium/policies/managed/color.json was simply never rewritten. Chasing it back to a failing theme hook took a while precisely because omarchy theme set kept reporting success.
The specific reason the path was missing is my own (a dev-linked checkout whose package predates commit bafc9a10, which added that helper) and is not what I am reporting. The point is that a hook exiting nonzero is currently unobservable, whatever the cause — the same applies to a hook that fails for any of the ordinary reasons.
This is also the mechanism that lets #10636's hang sit in a migration unnoticed until someone watches the log go quiet.
Expected
A failing hook should not abort the theme change — one broken retint should still leave the rest of the desktop themed, and I don't think that best-effort behaviour should change. But it should not pass for a clean run either.
Suggested fix
Collect the failures and name them on stderr, still returning zero. PR follows this issue.
Version
$ omarchy version
4.0.2Present identically on omacom/omarchy@quattro (verified at e848f1df) and omacom/omarchy-mac@quattro.
View raw text
## What happened
`omarchy theme set` reports success even when its post-theme hooks fail. `run_parallel` (`bin/omarchy-theme-set:33-45`) waits on each hook and throws the status away:
```bash
for pid in "${pids[@]}"; do
wait "$pid"
done
```
There is no `set -e` and no trap in the script, so nothing else catches it either. All fourteen entries in `post_theme_commands` — browser, vscode, obsidian, tmux, gnome, keyboard, the `restart-*` hooks — are unconditionally treated as having worked.
Reproducing with the function verbatim:
```bash
run_parallel() {
local pid
local pids=()
for command in "$@"; do
bash -lc "$command" &
pids+=("$!")
done
for pid in "${pids[@]}"; do
wait "$pid"
done
}
run_parallel "true" "exit 42" "nonexistent-command-xyz" "true"
echo "run_parallel returned: $?"
```
```
bash: line 1: nonexistent-command-xyz: command not found
run_parallel returned: 0
```
## Why it stays invisible
The exit status is discarded here, and on the normal interactive path the hook's stderr is discarded too — `shell/plugins/background/Background.qml:119`:
```qml
command: ["bash", "-c", "theme=$(omarchy-theme-switcher); [[ -n $theme ]] && omarchy-theme-set \"$theme\" >/dev/null 2>&1 &"]
```
So when a theme is changed from the picker, a broken hook produces no exit code, no message, and no notification. Nothing distinguishes it from a clean run, and the next theme change fails identically.
## How I hit it
On this machine `omarchy-theme-set-browser` had been failing on **every** theme change for 17 days and I never saw it. It exits 1 with:
```
Error accessing /usr/bin/omarchy-theme-set-browser-policy: No such file or directory
```
`omarchy-theme-set-browser-policy` re-execs its own packaged path (correctly — `etc/sudoers.d/omarchy-theme-browser` names `/usr/bin/omarchy-theme-set-browser-policy`, so the rule only matches from there), and on this install that path did not exist. The visible symptom was unrelated-looking: Chromium was stuck showing the `BrowserThemeColor` of a theme I had stopped using, because `/etc/chromium/policies/managed/color.json` was simply never rewritten. Chasing it back to a failing theme hook took a while precisely because `omarchy theme set` kept reporting success.
The specific reason the path was missing is my own (a dev-linked checkout whose package predates commit bafc9a10, which added that helper) and is not what I am reporting. The point is that a hook exiting nonzero is currently unobservable, whatever the cause — the same applies to a hook that fails for any of the ordinary reasons.
This is also the mechanism that lets #10636's hang sit in a migration unnoticed until someone watches the log go quiet.
## Expected
A failing hook should not abort the theme change — one broken retint should still leave the rest of the desktop themed, and I don't think that best-effort behaviour should change. But it should not pass for a clean run either.
## Suggested fix
Collect the failures and name them on stderr, still returning zero. PR follows this issue.
## Version
```
$ omarchy version
4.0.2
```
Present identically on `omacom/omarchy@quattro` (verified at e848f1df) and `omacom/omarchy-mac@quattro`.
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:06 UTC