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

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.

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

Post-resume fingerprint failure: lock screen activates fprintd inside logind's PrepareForSleep window, and the inhibitor-less daemon outlives the suspendrevision 1 · captured 2026-09-28 21:23 UTC via poll

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 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:

# /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.

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.