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 update` lock leaks through AUR daemons (adb), so later updates report one is already running
Reported by kdriedger · 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?
- 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?
- Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. So far: in the audited area (lock) — decided by agents · verified; matches no known issue — decided by agents · verified. The outcome (valid, duplicate, not a bug, …) is not decided yet. See the decision.
Original report
System details
- Omarchy: 4.0.0-1 (stable)
- Kernel: 7.1.8-arch1-3
- CPU: Intel Core i5-7300HQ
- GPU: Intel HD Graphics 630 + NVIDIA GeForce GTX 1050 Mobile
What's wrong?
After an omarchy update that touches AUR packages, later omarchy update runs abort immediately with:
An Omarchy update is already running.even though nothing is updating. The flock is still held by a daemon spawned during the previous update.
On this machine the leftover holder was adb, started from a flutter-beta AUR build:
$ fuser -v $XDG_RUNTIME_DIR/omarchy-update.lock
USER PID ACCESS COMMAND
/run/user/1000/omarchy-update.lock:
linuxbox 139567 F.... adb
$ ls -l /proc/139567/fd/10
/proc/139567/fd/10 -> /run/user/1000/omarchy-update.lock
$ tr '\0' ' ' < /proc/139567/cmdline; echo
adb -L tcp:5037 fork-server server --reply-fd 4
$ readlink /proc/139567/cwd
/home/linuxbox/.cache/yay/flutter-beta/src/flutter
$ ps -o pid,ppid,lstart,cmd -p 139567
# PPID is user systemd; the update that spawned it is long goneomarchy-update-lock opens the lock without O_CLOEXEC and execs the update:
exec {OMARCHY_UPDATE_LOCK_FD}>"$lock_path"
flock -n "$OMARCHY_UPDATE_LOCK_FD"
export OMARCHY_UPDATE_LOCK_FD
exec "$@"Every child inherits that fd. omarchy-update-aur-pkgs runs yay -Sua, and packages such as Flutter start adb which daemonizes onto user systemd and keeps the fd open after the update exits. The next omarchy-update-lock run then fails the non-blocking flock.
This is the same leak omarchy-update-stay-awake already special-cases for systemd-inhibit ({OMARCHY_UPDATE_LOCK_FD}>&-), and docs/update-process.md already documents why:
That inhibitor outlives the step that starts it, so an update killed before cleanup would otherwise leave it holding the flock indefinitely — blocking later updates
AUR/yay children are the same class of process and do not get that close.
Steps to reproduce
- Have an AUR package installed whose build or post-install starts a long-lived daemon that does not close extra fds (Flutter/
adbis a reliable one). - Run
omarchy updatefar enough foromarchy-update-aur-pkgs/yay -Suato run. - Let the update finish (or abort after that step). Confirm no
omarchy-updateprocess remains. - Run
omarchy updateagain.
Expected behavior
The lock is released when the omarchy update process tree exits. A later update can start.
Actual behavior
An Omarchy update is already running. The lock file is held by the leftover daemon (adb here). Removing the lock path (rm -f "$XDG_RUNTIME_DIR/omarchy-update.lock") unblocks the next run because the next open creates a new inode; killing the daemon also works.
Suggested fix
Do not let children inherit the lock fd. Two options that keep the current "parent holds the flock" model:
- After
omarchy-update-lock heldsucceeds, setFD_CLOEXEConOMARCHY_UPDATE_LOCK_FDso lateryay/adb/systemd-inhibitchildren cannot keep it.heldstill works in the update process itself because it inspects/proc/$$/fd. - Stop
execing the update into the lock-holder. Haveomarchy-update-lock runkeep the flock in the parent and spawn the update with the fd closed ({OMARCHY_UPDATE_LOCK_FD}>&-), using an env flag instead ofheldto avoid re-acquire. That is whatflock --closeis for.
Option 2 matches the stay-awake comment in docs/update-process.md and does not depend on every child remembering to close the fd.
Workaround
rm -f "${XDG_RUNTIME_DIR}/omarchy-update.lock"View raw text
### System details
- Omarchy: 4.0.0-1 (stable)
- Kernel: 7.1.8-arch1-3
- CPU: Intel Core i5-7300HQ
- GPU: Intel HD Graphics 630 + NVIDIA GeForce GTX 1050 Mobile
### What's wrong?
After an `omarchy update` that touches AUR packages, later `omarchy update` runs abort immediately with:
```
An Omarchy update is already running.
```
even though nothing is updating. The flock is still held by a daemon spawned during the previous update.
On this machine the leftover holder was `adb`, started from a `flutter-beta` AUR build:
```
$ fuser -v $XDG_RUNTIME_DIR/omarchy-update.lock
USER PID ACCESS COMMAND
/run/user/1000/omarchy-update.lock:
linuxbox 139567 F.... adb
$ ls -l /proc/139567/fd/10
/proc/139567/fd/10 -> /run/user/1000/omarchy-update.lock
$ tr '\0' ' ' < /proc/139567/cmdline; echo
adb -L tcp:5037 fork-server server --reply-fd 4
$ readlink /proc/139567/cwd
/home/linuxbox/.cache/yay/flutter-beta/src/flutter
$ ps -o pid,ppid,lstart,cmd -p 139567
# PPID is user systemd; the update that spawned it is long gone
```
`omarchy-update-lock` opens the lock without `O_CLOEXEC` and `exec`s the update:
```bash
exec {OMARCHY_UPDATE_LOCK_FD}>"$lock_path"
flock -n "$OMARCHY_UPDATE_LOCK_FD"
export OMARCHY_UPDATE_LOCK_FD
exec "$@"
```
Every child inherits that fd. `omarchy-update-aur-pkgs` runs `yay -Sua`, and packages such as Flutter start `adb` which daemonizes onto user systemd and keeps the fd open after the update exits. The next `omarchy-update-lock run` then fails the non-blocking flock.
This is the same leak `omarchy-update-stay-awake` already special-cases for `systemd-inhibit` (`{OMARCHY_UPDATE_LOCK_FD}>&-`), and `docs/update-process.md` already documents why:
> That inhibitor outlives the step that starts it, so an update killed before cleanup would otherwise leave it holding the flock indefinitely — blocking later updates
AUR/yay children are the same class of process and do not get that close.
#### Steps to reproduce
1. Have an AUR package installed whose build or post-install starts a long-lived daemon that does not close extra fds (Flutter/`adb` is a reliable one).
2. Run `omarchy update` far enough for `omarchy-update-aur-pkgs` / `yay -Sua` to run.
3. Let the update finish (or abort after that step). Confirm no `omarchy-update` process remains.
4. Run `omarchy update` again.
#### Expected behavior
The lock is released when the `omarchy update` process tree exits. A later update can start.
#### Actual behavior
`An Omarchy update is already running.` The lock file is held by the leftover daemon (`adb` here). Removing the lock path (`rm -f "$XDG_RUNTIME_DIR/omarchy-update.lock"`) unblocks the next run because the next open creates a new inode; killing the daemon also works.
#### Suggested fix
Do not let children inherit the lock fd. Two options that keep the current "parent holds the flock" model:
1. After `omarchy-update-lock held` succeeds, set `FD_CLOEXEC` on `OMARCHY_UPDATE_LOCK_FD` so later `yay`/`adb`/`systemd-inhibit` children cannot keep it. `held` still works in the update process itself because it inspects `/proc/$$/fd`.
2. Stop `exec`ing the update into the lock-holder. Have `omarchy-update-lock run` keep the flock in the parent and spawn the update with the fd closed (`{OMARCHY_UPDATE_LOCK_FD}>&-`), using an env flag instead of `held` to avoid re-acquire. That is what `flock --close` is for.
Option 2 matches the stay-awake comment in `docs/update-process.md` and does not depend on every child remembering to close the fd.
#### Workaround
```bash
rm -f "${XDG_RUNTIME_DIR}/omarchy-update.lock"
```
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
- Fixed bypr/8081· confirmed
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.
- Decided by agents · verified: in the audited area (lock)
- Decided by agents · verified: matches no known issue
The outcome (valid, duplicate, not a bug, …) is not decided yet.