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

Lock-on-suspend runs after PrepareForSleep(true), so pam_fprintd can never install fprintd's sleep delay inhibitor

Reported by wbnns · filed Sep 4, 2026Closed upstream on 2026-09-16 by its own reporter wbnns, as not planned. Closed by its own reporter — not by itself evidence of a fix.

Received and recorded verbatim. Nothing has been checked yet.

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?
Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.

Original report

Lock-on-suspend runs after PrepareForSleep(true), so pam_fprintd can never install fprintd's sleep delay inhibitorrevision 1 · captured 2026-10-04 12:10 UTC via poll

System details

ThinkPad X1 Carbon Gen 8 (20U9CTO1WW), Intel i7-10610U, Omarchy 4.0.2-1, kernel 7.1.9-arch1-2, systemd 261.2-1 (InhibitDelayMaxSec=15), quickshell 0.3.1-1, Hyprland 0.56.2-1, fprintd 1.94.5-2 / libfprint 1.94.100-1, Synaptics 06cb:00bd Prometheus MIS Touch reader, s2idle

What's wrong?

Reader detail: match-on-chip (STORAGE=True, STORAGE_LIST=False), libfprint synaptics driver. Stock omarchy-system-sleep-monitor, no local overrides.

omarchy-system-sleep-monitor takes its delay inhibitor, then waits for
PrepareForSleep(true) before locking:

# omarchy-system-sleep-monitor L11-L13
while IFS= read -r line; do
  if [[ $line == *"boolean true"* ]]; then    # PrepareForSleep(true)
    "$sleep_lock"                              # lock starts here

Because the lock starts after the signal, every process the lock screen activates is
already past the point where logind will accept a new sleep inhibitor. pam_fprintd is
one of them: the lock's omarchy-lock-fingerprint PAM stack D-Bus-activates fprintd,
fprintd asks logind for its own delay inhibitor, and logind refuses.

The reader is therefore opened for a verify with nothing holding sleep off, and is cut
mid-transaction when power drops.

Evidence

Ordering on one suspend (timestamps to 6 dp):

20:36:30.191477 systemd-logind[833]: Suspending...
20:36:30.468944 omarchy-shell[74919]: DEBUG qml: omarchy lock ... lock-requested
20:36:30.985598 fprintd[120179]: Failed to install a sleep delay inhibitor:
                GDBus.Error:org.freedesktop.login1.OperationInProgress:
                The operation inhibition has been requested for is already running
20:36:31.096764 omarchy-shell[120389]: quickshell.service.pam.subprocess: Starting pam
                session for user "..." with config "omarchy-lock-fingerprint"
20:36:31.310886 systemd[1]: Reached target Sleep.
20:36:31.379062 kernel: PM: suspend entry (s2idle)

The PAM session opens the reader at .096, and power drops at .379 — a 283 ms window
with no inhibitor. The ordering is identical in a second incident at 19:48:21.

This is not rare. Over 14 days: 8 inhibitor failures across 10 suspends.

$ journalctl -u fprintd --since "14 days ago" | grep -c "Failed to install a sleep delay inhibitor"
8
$ journalctl --since "14 days ago" | grep -c "PM: suspend entry"
10

On resume the device fully re-enumerates rather than being restored, despite
power/persist=1 and a matching serial — the device number climbs on each cycle:

22:15:45.593  PM: suspend exit
22:15:45.970  usb 1-9: USB disconnect, device number 11
22:15:46.216  usb 1-9: new full-speed USB device number 12
22:16:58.659  PM: suspend exit
22:16:59.600  usb 1-9: USB disconnect, device number 12
22:16:59.845  usb 1-9: new full-speed USB device number 13

Suspected consequence (observed once, not proven)

After one such cycle this reader's on-chip template storage came back empty. Every match
then failed:

fprintd[120179]: Device reported an error during identify:
                 Print was not found on the devices storage.

On a match-on-chip sensor the templates live in the reader's flash; the files under
/var/lib/fprint/<user>/synaptics/<serial>/ are 118-byte receipts holding only a format tag,
driver, serial, finger code, username and an ID. They contain no biometric data, so **the
templates cannot be restored — all fingers must be re-enrolled.**

Recovery also required clearing both sides. fprintd-delete alone was not enough: the chip
retained orphan templates it would not delete, and a fresh enroll wrote a host receipt while
the chip kept nothing. Only fp_device_clear_storage_sync() plus fprintd-delete gave a
working slate.

I want to be clear about the limit of this claim: the race is reproducible and shown above,
but that it caused the wipe is inference. The corruption happened once and I have not tried
to reproduce it, since doing so means destroying the enrollment again. Cutting a match-on-chip
sensor mid-transaction is a plausible mechanism for it, nothing more.

Note also that fprintd-verify reports this as verify-no-match, which actively misleads.
The real DATA_NOT_FOUND only appears in journalctl -u fprintd, which cost me a wrong
diagnosis before I checked the daemon log.

Expected

The lock screen should not open the fingerprint reader inside a sleep transition it cannot
inhibit. Either lock before signalling readiness for sleep, so activated helpers can still
register inhibitors, or leave fingerprint PAM disarmed for a suspend-triggered lock and arm it
on resume.

Workaround

A pre sleep hook that closes the device before power drops:

# /etc/systemd/system-sleep/50-fprintd-release
#!/bin/sh
case "$1" in
  pre) systemctl stop fprintd.service ;;
esac

fprintd is Type=dbus (BusName=net.reactivated.Fprint), so it re-activates on the next
touch and no post case is needed.

Related

  • #7280 and #8112 hit the same OperationInProgress string, but for

omarchy-sleep-lock.service re-acquiring its own inhibitor on restart. Same architectural
cause — work happening after PrepareForSleep — different affected process.
- #7229 is a stale fprintd handle after resume (Cannot run while suspended), addressed
with a post restart. This report is about the reader being cut during suspend entry, so
a post hook does not cover it.

View raw text
### System details

ThinkPad X1 Carbon Gen 8 (20U9CTO1WW), Intel i7-10610U, Omarchy 4.0.2-1, kernel 7.1.9-arch1-2, systemd 261.2-1 (InhibitDelayMaxSec=15), quickshell 0.3.1-1, Hyprland 0.56.2-1, fprintd 1.94.5-2 / libfprint 1.94.100-1, Synaptics 06cb:00bd Prometheus MIS Touch reader, s2idle

### What's wrong?

> Reader detail: match-on-chip (`STORAGE=True`, `STORAGE_LIST=False`), libfprint
> `synaptics` driver. Stock `omarchy-system-sleep-monitor`, no local overrides.

`omarchy-system-sleep-monitor` takes its delay inhibitor, then waits for
`PrepareForSleep(true)` before locking:

```bash
# omarchy-system-sleep-monitor L11-L13
while IFS= read -r line; do
  if [[ $line == *"boolean true"* ]]; then    # PrepareForSleep(true)
    "$sleep_lock"                              # lock starts here
```

Because the lock starts *after* the signal, every process the lock screen activates is
already past the point where logind will accept a new sleep inhibitor. `pam_fprintd` is
one of them: the lock's `omarchy-lock-fingerprint` PAM stack D-Bus-activates `fprintd`,
`fprintd` asks logind for its own `delay` inhibitor, and logind refuses.

The reader is therefore opened for a verify with **nothing holding sleep off**, and is cut
mid-transaction when power drops.

### Evidence

Ordering on one suspend (timestamps to 6 dp):

```text
20:36:30.191477 systemd-logind[833]: Suspending...
20:36:30.468944 omarchy-shell[74919]: DEBUG qml: omarchy lock ... lock-requested
20:36:30.985598 fprintd[120179]: Failed to install a sleep delay inhibitor:
                GDBus.Error:org.freedesktop.login1.OperationInProgress:
                The operation inhibition has been requested for is already running
20:36:31.096764 omarchy-shell[120389]: quickshell.service.pam.subprocess: Starting pam
                session for user "..." with config "omarchy-lock-fingerprint"
20:36:31.310886 systemd[1]: Reached target Sleep.
20:36:31.379062 kernel: PM: suspend entry (s2idle)
```

The PAM session opens the reader at `.096`, and power drops at `.379` — a **283 ms** window
with no inhibitor. The ordering is identical in a second incident at 19:48:21.

This is not rare. Over 14 days: **8 inhibitor failures across 10 suspends.**

```console
$ journalctl -u fprintd --since "14 days ago" | grep -c "Failed to install a sleep delay inhibitor"
8
$ journalctl --since "14 days ago" | grep -c "PM: suspend entry"
10
```

On resume the device fully re-enumerates rather than being restored, despite
`power/persist=1` and a matching serial — the device number climbs on each cycle:

```text
22:15:45.593  PM: suspend exit
22:15:45.970  usb 1-9: USB disconnect, device number 11
22:15:46.216  usb 1-9: new full-speed USB device number 12
22:16:58.659  PM: suspend exit
22:16:59.600  usb 1-9: USB disconnect, device number 12
22:16:59.845  usb 1-9: new full-speed USB device number 13
```

### Suspected consequence (observed once, not proven)

After one such cycle this reader's **on-chip template storage came back empty**. Every match
then failed:

```text
fprintd[120179]: Device reported an error during identify:
                 Print was not found on the devices storage.
```

On a match-on-chip sensor the templates live in the reader's flash; the files under
`/var/lib/fprint/<user>/synaptics/<serial>/` are 118-byte receipts holding only a format tag,
driver, serial, finger code, username and an ID. They contain no biometric data, so **the
templates cannot be restored — all fingers must be re-enrolled.**

Recovery also required clearing *both* sides. `fprintd-delete` alone was not enough: the chip
retained orphan templates it would not delete, and a fresh enroll wrote a host receipt while
the chip kept nothing. Only `fp_device_clear_storage_sync()` plus `fprintd-delete` gave a
working slate.

I want to be clear about the limit of this claim: the race is reproducible and shown above,
but that it *caused* the wipe is inference. The corruption happened once and I have not tried
to reproduce it, since doing so means destroying the enrollment again. Cutting a match-on-chip
sensor mid-transaction is a plausible mechanism for it, nothing more.

Note also that `fprintd-verify` reports this as `verify-no-match`, which actively misleads.
The real `DATA_NOT_FOUND` only appears in `journalctl -u fprintd`, which cost me a wrong
diagnosis before I checked the daemon log.

### Expected

The lock screen should not open the fingerprint reader inside a sleep transition it cannot
inhibit. Either lock before signalling readiness for sleep, so activated helpers can still
register inhibitors, or leave fingerprint PAM disarmed for a suspend-triggered lock and arm it
on resume.

### Workaround

A `pre` sleep hook that closes the device before power drops:

```sh
# /etc/systemd/system-sleep/50-fprintd-release
#!/bin/sh
case "$1" in
  pre) systemctl stop fprintd.service ;;
esac
```

`fprintd` is `Type=dbus` (`BusName=net.reactivated.Fprint`), so it re-activates on the next
touch and no `post` case is needed.

### Related

- #7280 and #8112 hit the same `OperationInProgress` string, but for
  `omarchy-sleep-lock.service` re-acquiring its own inhibitor on restart. Same architectural
  cause — work happening after `PrepareForSleep` — different affected process.
- #7229 is a stale `fprintd` handle *after* resume (`Cannot run while suspended`), addressed
  with a `post` restart. This report is about the reader being cut *during* suspend entry, so
  a `post` hook does not cover it.

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/9919· 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.

No decision has been recorded yet.