Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A 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.

Inbox
ReportR-2231GitHub issuePublicDecided· Out of scope

[stable 4.0.4] Interrupted update leaves root-owned inhibitor blocking suspend

Reported by argrig666 · filed Oct 4, 2026 · open at source

Decided: Out of scope — decided by agents · verified 3 days ago.

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

[stable 4.0.4] Interrupted update leaves root-owned inhibitor blocking suspendrevision 1 · captured 2026-10-04 04:17 UTC via poll

System details

  • Omarchy: 4.0.4-1 (stable)
  • Kernel: 7.2.5-3-omarchy
  • systemd: 261 (261.2-1-arch)
  • Architecture: x86_64

What's wrong?

An interrupted omarchy update can leave its privileged systemd-inhibit process running indefinitely. The inhibitor blocks both sleep and idle, so the system-menu Suspend action (systemctl suspend) silently fails even though no update or package operation remains active.

The leftover inhibitor was visible with systemd-inhibit --list:

WHO             WHAT        WHY                         MODE
omarchy-update  sleep:idle  Omarchy update in progress  block

The updater itself was gone, but this process chain had survived for about eight hours:

sudo systemd-inhibit --what=sleep:idle --who=omarchy-update \
  --why="Omarchy update in progress" --mode=block sleep infinity
  └─ sudo systemd-inhibit ...
     └─ systemd-inhibit ...
        └─ sleep infinity

The state file recorded the first sudo wrapper PID:

$ cat "$XDG_RUNTIME_DIR/omarchy-update-stay-awake/inhibit-pid"
139215 295390

That PID was root-owned. omarchy-update-stay-awake stop runs as the desktop user and executes:

kill "$inhibit_pid" >/dev/null 2>&1 || true

The signal therefore fails with EPERM. The subsequent start-time check sees the process still alive and reports:

Failed to stop the Omarchy update sleep inhibitor.

Because start() begins by calling stop, later update attempts do not recover the stale inhibitor either.

Steps to reproduce

  1. Start omarchy update and let it reach omarchy-update-stay-awake start.
  2. Interrupt or kill the updater before its normal cleanup completes.
  3. Confirm there is no remaining omarchy-update, pacman, yay, or paru operation.
  4. Run systemd-inhibit --list; the root-owned omarchy-update blocker remains.
  5. Run omarchy update stay awake stop as the desktop user; it cannot kill the recorded root-owned PID.
  6. Select Suspend from the system menu or run systemctl suspend; logind refuses the operation because the block inhibitor remains.

Expected behavior

Update cleanup should reliably terminate its own privileged sleep inhibitor. A later start or stop invocation should also recover a stale inhibitor after an interrupted update.

Actual behavior

The root-owned inhibitor survives after the update is gone and blocks suspend indefinitely, until the process is terminated with privilege or the machine is rebooted.

Likely cause

omarchy-update-stay-awake start launches sudo systemd-inhibit ... & and stores $!. That PID belongs to the privileged sudo process by the time cleanup runs. stop later attempts an ordinary unprivileged kill, suppresses its failure, and cannot release the inhibitor.

This appears hardware-independent. The symptom initially looked like a Dell/NVIDIA suspend problem, but the journal showed no new suspend attempt; after terminating only the stale inhibitor, suspend was unblocked.

Possible direction

Keep an unprivileged supervisor PID that can be signaled by the user and have it own/reap the privileged child, or make stop use the update's established privileged-command boundary to terminate the validated PID. The existing PID start-time check should remain to avoid PID-reuse mistakes.

Related but distinct: #8077 concerns children inheriting the update lock fd. This report concerns the update-owned sleep inhibitor itself surviving cleanup and blocking suspend.

View raw text
### System details

- Omarchy: 4.0.4-1 (stable)
- Kernel: 7.2.5-3-omarchy
- systemd: 261 (261.2-1-arch)
- Architecture: x86_64

### What's wrong?

An interrupted `omarchy update` can leave its privileged `systemd-inhibit` process running indefinitely. The inhibitor blocks both `sleep` and `idle`, so the system-menu Suspend action (`systemctl suspend`) silently fails even though no update or package operation remains active.

The leftover inhibitor was visible with `systemd-inhibit --list`:

```text
WHO             WHAT        WHY                         MODE
omarchy-update  sleep:idle  Omarchy update in progress  block
```

The updater itself was gone, but this process chain had survived for about eight hours:

```text
sudo systemd-inhibit --what=sleep:idle --who=omarchy-update \
  --why="Omarchy update in progress" --mode=block sleep infinity
  └─ sudo systemd-inhibit ...
     └─ systemd-inhibit ...
        └─ sleep infinity
```

The state file recorded the first `sudo` wrapper PID:

```text
$ cat "$XDG_RUNTIME_DIR/omarchy-update-stay-awake/inhibit-pid"
139215 295390
```

That PID was root-owned. `omarchy-update-stay-awake stop` runs as the desktop user and executes:

```bash
kill "$inhibit_pid" >/dev/null 2>&1 || true
```

The signal therefore fails with `EPERM`. The subsequent start-time check sees the process still alive and reports:

```text
Failed to stop the Omarchy update sleep inhibitor.
```

Because `start()` begins by calling `stop`, later update attempts do not recover the stale inhibitor either.

### Steps to reproduce

1. Start `omarchy update` and let it reach `omarchy-update-stay-awake start`.
2. Interrupt or kill the updater before its normal cleanup completes.
3. Confirm there is no remaining `omarchy-update`, `pacman`, `yay`, or `paru` operation.
4. Run `systemd-inhibit --list`; the root-owned `omarchy-update` blocker remains.
5. Run `omarchy update stay awake stop` as the desktop user; it cannot kill the recorded root-owned PID.
6. Select Suspend from the system menu or run `systemctl suspend`; logind refuses the operation because the block inhibitor remains.

### Expected behavior

Update cleanup should reliably terminate its own privileged sleep inhibitor. A later `start` or `stop` invocation should also recover a stale inhibitor after an interrupted update.

### Actual behavior

The root-owned inhibitor survives after the update is gone and blocks suspend indefinitely, until the process is terminated with privilege or the machine is rebooted.

### Likely cause

`omarchy-update-stay-awake start` launches `sudo systemd-inhibit ... &` and stores `$!`. That PID belongs to the privileged `sudo` process by the time cleanup runs. `stop` later attempts an ordinary unprivileged `kill`, suppresses its failure, and cannot release the inhibitor.

This appears hardware-independent. The symptom initially looked like a Dell/NVIDIA suspend problem, but the journal showed no new suspend attempt; after terminating only the stale inhibitor, suspend was unblocked.

### Possible direction

Keep an unprivileged supervisor PID that can be signaled by the user and have it own/reap the privileged child, or make `stop` use the update's established privileged-command boundary to terminate the validated PID. The existing PID start-time check should remain to avoid PID-reuse mistakes.

Related but distinct: #8077 concerns children inheriting the update lock fd. This report concerns the update-owned sleep inhibitor itself surviving cleanup and blocking suspend.

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 21:11 UTC