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-1720GitHub issuePublicFixed

omarchy-sleep-lock.service fails on resume: Restart=always re-runs systemd-inhibit while logind's sleep operation is still in flight

Reported by ki11e6 · filed Aug 17, 2026 · open at source

Decided: Duplicate — decided by agents · verified 3 days ago.

This defect is tracked under R-131. This report describes the same defect, so it is folded under it in the inbox.

Earliest report of this defect: R-1720 (filed Aug 17, 2026).

Decided by agents · verified· Oct 9, 2026

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?
Not yet mapped to any requirement or component.
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

omarchy-sleep-lock.service fails on resume: Restart=always re-runs systemd-inhibit while logind's sleep operation is still in flightrevision 1 · captured 2026-09-28 21:29 UTC via poll

System details

  • Omarchy 4.0.0-1 (stable, not Quattro)
  • Arch Linux kernel 7.1.8-arch1-3
  • systemd 261 (261.2-1-arch)
  • Quickshell 0.3.0.r20.g28771c7-1
  • Hyprland 0.56.2-1 / Aquamarine 0.14.0-2
  • ASUS TUF Gaming FX505GT, Intel i5-9300H, hybrid Intel UHD 630 + NVIDIA GTX 1650 Mobile
  • Sleep state deep (S3), /sys/power/mem_sleep = s2idle [deep]
  • Shipped InhibitDelayMaxSec=15 drop-in active
  • Stock omarchy-sleep-lock.service and omarchy-system-sleep-monitor, no local overrides

What's wrong?

Summary

The fix for #6394 works as intended — omarchy-system-sleep-monitor now releases its delay
inhibitor as soon as the lock is secure, because the --inhibited branch returns after
consume_sleep_events runs the lock helper. But omarchy-sleep-lock.service is Restart=always
with RestartSec=2s, so systemd immediately restarts the unit — and **that restart lands while
logind's sleep operation is still in flight**, so systemd-inhibit refuses to register a new sleep
inhibitor and the unit exits 1.

The result is a spurious unit failure on resume, plus a ~2 s window in which **no Omarchy delay
inhibitor is registered at all**. I have one trace (see Notes), but the mechanism is visible in the
shipped source and the unit properties, so I would expect it on every resume.

Evidence

From journalctl on the resume (timestamps to 6 dp so the ordering is unambiguous):

18:41:01.620675 systemd[1003]: omarchy-sleep-lock.service: Scheduled restart job, restart counter is at 1.
18:41:01.634564 systemd[1003]: Started Lock Omarchy before suspend.
18:41:01.757854 systemd-inhibit[387442]: Failed to inhibit: The operation inhibition has been requested for is already running
18:41:01.759766 systemd[1003]: omarchy-sleep-lock.service: Main process exited, code=exited, status=1/FAILURE
18:41:01.759919 systemd[1003]: omarchy-sleep-lock.service: Failed with result 'exit-code'.
18:41:02.491985 systemd-logind[870]: Operation 'suspend' finished.
18:41:03.811668 systemd[1003]: omarchy-sleep-lock.service: Scheduled restart job, restart counter is at 2.
18:41:03.816155 systemd[1003]: Started Lock Omarchy before suspend.

The decisive ordering is the middle two lines: systemd-inhibit fails at 18:41:01.757854, and
logind only reports Operation 'suspend' finished at 18:41:02.491985 — 734 ms later. The
restart is therefore attempting to take a --what=sleep inhibitor while logind still considers the
sleep operation active, which is exactly the condition that produces "the operation inhibition has
been requested for is already running".

The retry 2 s later succeeds (restart counter is at 2), because by then the sleep operation has
finished. Locking itself was never affected — the lock went secure normally before suspend:

15:58:21.253 omarchy-shell[1187]: DEBUG qml: omarchy lock ... lock-requested
15:58:21.869 omarchy-shell[1187]: DEBUG qml: omarchy lock ... secure=true

Unit properties, for the record:

$ systemctl --user show omarchy-sleep-lock.service \
    -p Restart -p RestartUSec -p StartLimitBurst -p StartLimitIntervalUSec
Restart=always
RestartUSec=2s
StartLimitBurst=5
StartLimitIntervalUSec=10s

Expected result

A resume should not leave omarchy-sleep-lock.service in a failed state, and the delay inhibitor
should be re-registered without a gap. Releasing the inhibitor promptly (the #6394 fix) and
re-acquiring it reliably should not be in tension.

Actual result

The resume produced one status=1/FAILURE, and the inhibitor was missing for ~2.06 s
(18:41:01.759919 → 18:41:03.816155).

Impact — deliberately not overstated

  • The failure is self-healing: the second restart succeeds. Locking before suspend worked

correctly — this affects the window after resume, not the lock itself.
- Exposure requires a suspend to be triggered inside the ~2 s gap. In practice the session is
normally still locked from the previous suspend at that moment, so I have not observed an
unlocked-suspend as a result of this, and I am not claiming one.
- I specifically checked whether the rate limiter could latch the unit off permanently — it cannot
via this path. One failure per resume against StartLimitBurst=5 / StartLimitIntervalSec=10s
would need five suspend/resume cycles inside 10 s.

So: low severity, but a real defect, and it makes every resume log a unit failure that looks alarming
while investigating unrelated suspend problems — which is how I found it.

Reproduction

  1. Stock omarchy-sleep-lock.service / omarchy-system-sleep-monitor on Omarchy 4.0.0.
  2. From an active, unlocked session, run systemctl suspend.
  3. Resume.
  4. journalctl --user -u omarchy-sleep-lock.service -b and

journalctl -b | grep -E "Failed to inhibit|Operation 'suspend' finished".
5. Observe the Failed to inhibit / status=1/FAILURE pair, followed by a successful restart 2 s
later, and note that Operation 'suspend' finished is logged after the failure.

Possible directions (neither tested — offered only as a starting point)

  1. Retry instead of failing. Have the wrapper treat "the operation inhibition has been requested

for is already running" as retryable rather than fatal, so the unit does not enter a failed state
for a transient condition it will win a moment later.
2. Decouple watching from inhibiting. The process needs to be long-lived to watch
PrepareForSleep, but the inhibitor only needs to be held around each sleep. systemd-inhibit CMD
couples the two lifetimes, which is what forces the exit-and-restart cycle in the first place.
Holding the inhibitor via a file descriptor (org.freedesktop.login1.Manager.Inhibit) and
releasing it on secure=true would let one persistent monitor serve every sleep cycle without
ever restarting.

Direction 2 looks structurally cleaner but is a larger change; direction 1 is minimal. I have not
implemented or tested either, so treat both as suggestions rather than proposals.

Notes

  • Observed on the first and so far only suspend/resume cycle on this machine, so n=1 — though

the mechanism is visible in the shipped source and the unit properties, not just in the one trace.
- Related: #6394 (the fix whose success creates this race). Distinct from #6359, which was a stale
hyprlock process — there is no stale lock process here, and locking succeeded.
- Found while diagnosing a separate NVIDIA suspend/resume compositor hang on the same resume; that
part is #4891 and is not an Omarchy bug, so it is not reported here.

View raw text
### System details

- Omarchy `4.0.0-1` (stable, **not** Quattro)
- Arch Linux kernel `7.1.8-arch1-3`
- systemd `261 (261.2-1-arch)`
- Quickshell `0.3.0.r20.g28771c7-1`
- Hyprland `0.56.2-1` / Aquamarine `0.14.0-2`
- ASUS TUF Gaming FX505GT, Intel i5-9300H, hybrid Intel UHD 630 + NVIDIA GTX 1650 Mobile
- Sleep state `deep` (S3), `/sys/power/mem_sleep` = `s2idle [deep]`
- Shipped `InhibitDelayMaxSec=15` drop-in active
- Stock `omarchy-sleep-lock.service` and `omarchy-system-sleep-monitor`, no local overrides

### What's wrong?

#### Summary

The fix for #6394 works as intended — `omarchy-system-sleep-monitor` now releases its delay
inhibitor as soon as the lock is secure, because the `--inhibited` branch returns after
`consume_sleep_events` runs the lock helper. But `omarchy-sleep-lock.service` is `Restart=always`
with `RestartSec=2s`, so systemd immediately restarts the unit — and **that restart lands while
logind's sleep operation is still in flight**, so `systemd-inhibit` refuses to register a new sleep
inhibitor and the unit exits `1`.

The result is a spurious unit failure on resume, plus a ~2 s window in which **no Omarchy delay
inhibitor is registered at all**. I have one trace (see Notes), but the mechanism is visible in the
shipped source and the unit properties, so I would expect it on every resume.

#### Evidence

From `journalctl` on the resume (timestamps to 6 dp so the ordering is unambiguous):

```text
18:41:01.620675 systemd[1003]: omarchy-sleep-lock.service: Scheduled restart job, restart counter is at 1.
18:41:01.634564 systemd[1003]: Started Lock Omarchy before suspend.
18:41:01.757854 systemd-inhibit[387442]: Failed to inhibit: The operation inhibition has been requested for is already running
18:41:01.759766 systemd[1003]: omarchy-sleep-lock.service: Main process exited, code=exited, status=1/FAILURE
18:41:01.759919 systemd[1003]: omarchy-sleep-lock.service: Failed with result 'exit-code'.
18:41:02.491985 systemd-logind[870]: Operation 'suspend' finished.
18:41:03.811668 systemd[1003]: omarchy-sleep-lock.service: Scheduled restart job, restart counter is at 2.
18:41:03.816155 systemd[1003]: Started Lock Omarchy before suspend.
```

The decisive ordering is the middle two lines: `systemd-inhibit` fails at `18:41:01.757854`, and
logind only reports `Operation 'suspend' finished` at `18:41:02.491985` — **734 ms later**. The
restart is therefore attempting to take a `--what=sleep` inhibitor while logind still considers the
sleep operation active, which is exactly the condition that produces "the operation inhibition has
been requested for is already running".

The retry 2 s later succeeds (`restart counter is at 2`), because by then the sleep operation has
finished. Locking itself was never affected — the lock went secure normally *before* suspend:

```text
15:58:21.253 omarchy-shell[1187]: DEBUG qml: omarchy lock ... lock-requested
15:58:21.869 omarchy-shell[1187]: DEBUG qml: omarchy lock ... secure=true
```

Unit properties, for the record:

```console
$ systemctl --user show omarchy-sleep-lock.service \
    -p Restart -p RestartUSec -p StartLimitBurst -p StartLimitIntervalUSec
Restart=always
RestartUSec=2s
StartLimitBurst=5
StartLimitIntervalUSec=10s
```

#### Expected result

A resume should not leave `omarchy-sleep-lock.service` in a failed state, and the delay inhibitor
should be re-registered without a gap. Releasing the inhibitor promptly (the #6394 fix) and
re-acquiring it reliably should not be in tension.

#### Actual result

The resume produced one `status=1/FAILURE`, and the inhibitor was missing for ~2.06 s
(`18:41:01.759919` → `18:41:03.816155`).

#### Impact — deliberately not overstated

- The failure is **self-healing**: the second restart succeeds. Locking before suspend worked
  correctly — this affects the window *after* resume, not the lock itself.
- Exposure requires a suspend to be triggered inside the ~2 s gap. In practice the session is
  normally still locked from the previous suspend at that moment, so I have **not** observed an
  unlocked-suspend as a result of this, and I am not claiming one.
- I specifically checked whether the rate limiter could latch the unit off permanently — it cannot
  via this path. One failure per resume against `StartLimitBurst=5` / `StartLimitIntervalSec=10s`
  would need five suspend/resume cycles inside 10 s.

So: low severity, but a real defect, and it makes every resume log a unit failure that looks alarming
while investigating unrelated suspend problems — which is how I found it.

#### Reproduction

1. Stock `omarchy-sleep-lock.service` / `omarchy-system-sleep-monitor` on Omarchy 4.0.0.
2. From an active, unlocked session, run `systemctl suspend`.
3. Resume.
4. `journalctl --user -u omarchy-sleep-lock.service -b` and
   `journalctl -b | grep -E "Failed to inhibit|Operation 'suspend' finished"`.
5. Observe the `Failed to inhibit` / `status=1/FAILURE` pair, followed by a successful restart 2 s
   later, and note that `Operation 'suspend' finished` is logged *after* the failure.

#### Possible directions (neither tested — offered only as a starting point)

1. **Retry instead of failing.** Have the wrapper treat "the operation inhibition has been requested
   for is already running" as retryable rather than fatal, so the unit does not enter a failed state
   for a transient condition it will win a moment later.
2. **Decouple watching from inhibiting.** The process needs to be long-lived to watch
   `PrepareForSleep`, but the inhibitor only needs to be held around each sleep. `systemd-inhibit CMD`
   couples the two lifetimes, which is what forces the exit-and-restart cycle in the first place.
   Holding the inhibitor via a file descriptor (`org.freedesktop.login1.Manager.Inhibit`) and
   releasing it on `secure=true` would let one persistent monitor serve every sleep cycle without
   ever restarting.

Direction 2 looks structurally cleaner but is a larger change; direction 1 is minimal. I have not
implemented or tested either, so treat both as suggestions rather than proposals.

### Notes

- Observed on the **first and so far only** suspend/resume cycle on this machine, so `n=1` — though
  the mechanism is visible in the shipped source and the unit properties, not just in the one trace.
- Related: #6394 (the fix whose success creates this race). Distinct from #6359, which was a stale
  `hyprlock` process — there is no stale lock process here, and locking succeeded.
- Found while diagnosing a separate NVIDIA suspend/resume compositor hang on the same resume; that
  part is #4891 and is not an Omarchy bug, so it is not reported here.

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

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.

  • DuplicateR-131Decided by agents · verified · 2026-10-09 03:19 UTC