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.
Post-resume fingerprint failure: lock screen activates fprintd inside logind's PrepareForSleep window, and the inhibitor-less daemon outlives the suspend
Reported by ilajosmanov · filed Sep 20, 2026Closed upstream on 2026-10-04 by the bot omarchybot; the closing comment says it was fixed by PR #7158. GitHub close reason: completed.
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
What happened
Fingerprint unlock is dead on resume, and pam_fprintd fails with code 9 (PAM_AUTHINFO_UNAVAIL) from the very first attempt, for ~55 seconds after the lid opens. Then it silently starts working again.
The cause is a stale fprintd process that was D-Bus-activated inside logind's PrepareForSleep(true) window and then outlived the entire suspend.
This is the root cause of the post-resume case described in #12509's comment — same hardware (Framework, Goodix MOC 27c6:609c), same "code 9 from the first attempt at resume". That comment correctly identifies the retry loop as an amplifier and notes the VT/polkit path, but says "the post-resume sensor failure itself persists" without explaining why it starts. This is why.
The trace
01:07:48 systemd-logind: Lid closed.
01:07:48 systemd-logind: Suspending... <- PrepareForSleep(true), 15s delay window opens
01:07:49 omarchy-shell: omarchy lock ... lock-requested
01:07:49 systemd: Starting Fingerprint Authentication Daemon...
01:07:49 fprintd[215029]: Failed to install a sleep delay inhibitor:
GDBus.Error:org.freedesktop.login1.OperationInProgress:
The operation inhibition has been requested for is already running
01:07:49 kernel: PM: suspend entry (s2idle)The lock path arms pam_fprintd, which D-Bus-activates fprintd at the one moment logind refuses new delay inhibitors. fprintd 215029 is now running without a sleep inhibitor.
That much happens on every lid-close suspend on this machine — 08:06:59, 08:13:46, 23:55:33, 00:49:20, 01:07:49 all log it. Normally it is harmless, because the instance idle-exits (~30s) while the machine is away.
It only becomes destructive when a second suspend follows:
01:08:01 kernel: PM: suspend exit <- spurious wake, lid still closed
01:08:01 kernel: usb 1-2: new high-speed USB device ... (dock/charger enumerating)
01:08:01 omarchy-shell: Relaying pam message: "Place your right index finger on the fingerprint reader"
01:08:27 fprintd[215029]: Device reported an error during verify: Cannot run while suspended.
01:08:27 systemd-logind: Suspending... <- lid still closed, so straight back down
01:08:28 kernel: PM: suspend entry (s2idle)fprintd 215029 is now subscribed to PrepareForSleep, so this time it does call fp_device_suspend() — flagging the device suspended and aborting the verify that was waiting for a finger. The machine then suspends with that flag set inside an inhibitor-less daemon.
02:02:05 systemd-logind: Lid opened.
02:02:05 kernel: PM: suspend exit
02:02:05 omarchy-shell: Error while authenticating: "Authentication service cannot
retrieve authentication info" (code 9) <- first attempt, immediately
... ~45 more identical failures over 25s (this is #12509's loop)
02:02:31 omarchy-shell: config "omarchy-lock-password" -> Authenticated successfully.
02:03:01 systemd: fprintd.service: Deactivated successfully. <- 215029 finally exitsPID 215029 — born at 01:07:49, before a 54-minute sleep — is still the process answering at 02:02:05. fprintd logs nothing at all during the storm; it never gets far enough to verify.
Once it exits, the device is completely healthy. During the failure window fprintd-list confirms the hardware and enrollment are fine:
Fingerprints for user io on Goodix MOC Fingerprint Sensor (press):
- #0: right-index-fingerWhy the broken daemon survives the suspend
fprintd idle-exits ~30s after its last activity (measured on clean cycles: 19:48:14→19:48:54, 21:31:44→21:32:16, 19:49:59→19:50:32).
Its GLib timer runs on CLOCK_MONOTONIC, which does not advance across s2idle. Last activity 01:08:27, then 54 minutes of frozen clock. It exits at 02:03:01 — exactly 31s after resume-side activity stopped at 02:02:30.
So a process that should have died in half a minute is the one that greets you an hour later, holding the reader.
Relationship to existing issues
- #12509 — the ~400ms retry loop. That is the amplifier; this issue is one of the upstream faults it amplifies. Fixing either alone leaves a real bug.
- #12495 —
omarchy-sleep-lock.servicehitting the same logindOperationInProgresserror in the same window. That issue correctly concludes it is "log noise, not functional breakage" for that service. Worth noting that the same window is not benign forfprintd: there the missing inhibitor poisons the reader across the sleep.
Workaround (verified on this machine)
A resume hook that drops any daemon carried over from before the suspend:
# /usr/lib/systemd/system-sleep/restart-fprintd
if [[ $1 == "post" ]]; then
if systemctl is-active --quiet fprintd.service; then
timeout --kill-after=1s 5s systemctl stop fprintd.service 2>/dev/null ||
systemctl kill --signal=KILL fprintd.service 2>/dev/null || true
fi
fipost rather than pre is deliberate: at pre the lock screen is still retrying, so a stopped daemon is re-activated within the same sleep window and lands in the same inhibitor-less state. At post, PrepareForSleep(false) has already gone out and the next activation takes its inhibitor normally.
Confirmed working — Deactivated successfully now lands on the same second as PM: suspend exit instead of ~30s later.
Note for anyone reproducing: on systemd 261 only /usr/lib/systemd/system-sleep/ is scanned. /etc/systemd/system-sleep/ is not read, and a hook placed there silently never runs.
Suggested fix
Don't arm the fingerprint PAM stack while a sleep operation is in progress. The pre-suspend lock has to happen inside the inhibitor window — that is the whole point of omarchy-system-sleep-lock — but it does not need fingerprint auth armed, since nobody is going to touch the reader on a closing lid. Deferring the fingerprint PamContext until after PrepareForSleep(false) (and arming it then) avoids creating the poisoned daemon in the first place.
A cheaper mitigation, if that is awkward in the shell: have the resume path stop fprintd.service, as the hook above does.
Environment
- Omarchy 4.0.4-1 (
/usr/share/omarchy/version: 4.0.0.alpha), Arch - Kernel
7.2.5-3-omarchy, systemd 261 (261.2-1-arch) - quickshell 0.3.1-1
- fprintd 1.94.5-2, libfprint-git 1:1.94.100.r10.g6f9479c-1
- Framework Laptop (AMD), Goodix MOC Fingerprint Sensor
27c6:609c InhibitDelayMaxSec=15(stock Omarchy drop-in,20-inhibit-delay.conf)
Caveat
Traced from logs of a single occurrence rather than reproduced on demand. The inhibitor failure on every lid-close suspend is directly observed and consistent; the specific double-suspend that makes it stick came from plugging in a dock while the lid was closed. Suspected repro: close lid → plug the charger/dock in while closed → open lid.
Filed by Claude Opus 5 via Claude Code.
View raw text
## What happened
Fingerprint unlock is dead on resume, and `pam_fprintd` fails with code 9 (`PAM_AUTHINFO_UNAVAIL`) **from the very first attempt**, for ~55 seconds after the lid opens. Then it silently starts working again.
The cause is a stale `fprintd` process that was D-Bus-activated *inside* logind's `PrepareForSleep(true)` window and then outlived the entire suspend.
This is the root cause of the post-resume case described in [#12509](https://github.com/basecamp/omarchy/issues/12509)'s comment — same hardware (Framework, Goodix MOC `27c6:609c`), same "code 9 from the first attempt at resume". That comment correctly identifies the retry loop as an amplifier and notes the VT/polkit path, but says "the post-resume sensor failure itself persists" without explaining why it starts. This is why.
## The trace
```
01:07:48 systemd-logind: Lid closed.
01:07:48 systemd-logind: Suspending... <- PrepareForSleep(true), 15s delay window opens
01:07:49 omarchy-shell: omarchy lock ... lock-requested
01:07:49 systemd: Starting Fingerprint Authentication Daemon...
01:07:49 fprintd[215029]: Failed to install a sleep delay inhibitor:
GDBus.Error:org.freedesktop.login1.OperationInProgress:
The operation inhibition has been requested for is already running
01:07:49 kernel: PM: suspend entry (s2idle)
```
The lock path arms `pam_fprintd`, which D-Bus-activates `fprintd` at the one moment logind refuses new delay inhibitors. `fprintd` 215029 is now running **without a sleep inhibitor**.
That much happens on *every* lid-close suspend on this machine — 08:06:59, 08:13:46, 23:55:33, 00:49:20, 01:07:49 all log it. Normally it is harmless, because the instance idle-exits (~30s) while the machine is away.
It only becomes destructive when a second suspend follows:
```
01:08:01 kernel: PM: suspend exit <- spurious wake, lid still closed
01:08:01 kernel: usb 1-2: new high-speed USB device ... (dock/charger enumerating)
01:08:01 omarchy-shell: Relaying pam message: "Place your right index finger on the fingerprint reader"
01:08:27 fprintd[215029]: Device reported an error during verify: Cannot run while suspended.
01:08:27 systemd-logind: Suspending... <- lid still closed, so straight back down
01:08:28 kernel: PM: suspend entry (s2idle)
```
`fprintd` 215029 is now subscribed to `PrepareForSleep`, so this time it *does* call `fp_device_suspend()` — flagging the device suspended and aborting the verify that was waiting for a finger. The machine then suspends with that flag set inside an inhibitor-less daemon.
```
02:02:05 systemd-logind: Lid opened.
02:02:05 kernel: PM: suspend exit
02:02:05 omarchy-shell: Error while authenticating: "Authentication service cannot
retrieve authentication info" (code 9) <- first attempt, immediately
... ~45 more identical failures over 25s (this is #12509's loop)
02:02:31 omarchy-shell: config "omarchy-lock-password" -> Authenticated successfully.
02:03:01 systemd: fprintd.service: Deactivated successfully. <- 215029 finally exits
```
PID 215029 — born at 01:07:49, before a 54-minute sleep — is still the process answering at 02:02:05. `fprintd` logs nothing at all during the storm; it never gets far enough to verify.
Once it exits, the device is completely healthy. During the failure window `fprintd-list` confirms the hardware and enrollment are fine:
```
Fingerprints for user io on Goodix MOC Fingerprint Sensor (press):
- #0: right-index-finger
```
## Why the broken daemon survives the suspend
`fprintd` idle-exits ~30s after its last activity (measured on clean cycles: 19:48:14→19:48:54, 21:31:44→21:32:16, 19:49:59→19:50:32).
Its GLib timer runs on `CLOCK_MONOTONIC`, **which does not advance across s2idle**. Last activity 01:08:27, then 54 minutes of frozen clock. It exits at 02:03:01 — exactly 31s after resume-side activity stopped at 02:02:30.
So a process that should have died in half a minute is the one that greets you an hour later, holding the reader.
## Relationship to existing issues
- **#12509** — the ~400ms retry loop. That is the amplifier; this issue is one of the upstream faults it amplifies. Fixing either alone leaves a real bug.
- **#12495** — `omarchy-sleep-lock.service` hitting the *same* logind `OperationInProgress` error in the *same* window. That issue correctly concludes it is "log noise, not functional breakage" for that service. Worth noting that the same window is not benign for `fprintd`: there the missing inhibitor poisons the reader across the sleep.
## Workaround (verified on this machine)
A resume hook that drops any daemon carried over from before the suspend:
```bash
# /usr/lib/systemd/system-sleep/restart-fprintd
if [[ $1 == "post" ]]; then
if systemctl is-active --quiet fprintd.service; then
timeout --kill-after=1s 5s systemctl stop fprintd.service 2>/dev/null ||
systemctl kill --signal=KILL fprintd.service 2>/dev/null || true
fi
fi
```
`post` rather than `pre` is deliberate: at `pre` the lock screen is still retrying, so a stopped daemon is re-activated within the same sleep window and lands in the same inhibitor-less state. At `post`, `PrepareForSleep(false)` has already gone out and the next activation takes its inhibitor normally.
Confirmed working — `Deactivated successfully` now lands on the same second as `PM: suspend exit` instead of ~30s later.
Note for anyone reproducing: on systemd 261 only `/usr/lib/systemd/system-sleep/` is scanned. `/etc/systemd/system-sleep/` is **not** read, and a hook placed there silently never runs.
## Suggested fix
Don't arm the fingerprint PAM stack while a sleep operation is in progress. The pre-suspend lock has to happen inside the inhibitor window — that is the whole point of `omarchy-system-sleep-lock` — but it does not need fingerprint auth armed, since nobody is going to touch the reader on a closing lid. Deferring the fingerprint `PamContext` until after `PrepareForSleep(false)` (and arming it then) avoids creating the poisoned daemon in the first place.
A cheaper mitigation, if that is awkward in the shell: have the resume path stop `fprintd.service`, as the hook above does.
## Environment
- Omarchy 4.0.4-1 (`/usr/share/omarchy/version`: 4.0.0.alpha), Arch
- Kernel `7.2.5-3-omarchy`, systemd 261 (261.2-1-arch)
- quickshell 0.3.1-1
- fprintd 1.94.5-2, libfprint-git 1:1.94.100.r10.g6f9479c-1
- Framework Laptop (AMD), Goodix MOC Fingerprint Sensor `27c6:609c`
- `InhibitDelayMaxSec=15` (stock Omarchy drop-in, `20-inhibit-delay.conf`)
## Caveat
Traced from logs of a single occurrence rather than reproduced on demand. The inhibitor failure on every lid-close suspend is directly observed and consistent; the specific double-suspend that makes it stick came from plugging in a dock while the lid was closed. Suspected repro: close lid → plug the charger/dock in while closed → open lid.
Filed by Claude Opus 5 via Claude Code.
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.