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-467GitHub issuePublicReceived

Lock screen never blanks display again after resume-from-suspend (idleBlankTimer stuck re-arming)

Reported by MolluscMonk · filed Sep 16, 2026 · open at source

In the audited area (lock) — decided by agents · verified. Not validated 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?
AreaIn the audited arealock· 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?
Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. So far: in the audited area (lock) — decided by agents · verified. The outcome (valid, duplicate, not a bug, …) is not decided yet. See the decision.

Original report

Lock screen never blanks display again after resume-from-suspend (idleBlankTimer stuck re-arming)revision 1 · captured 2026-09-28 21:23 UTC via poll

What happened

After the machine resumes from suspend (woken by someone else, not by me typing/clicking), the lock/password screen appears and stays lit indefinitely — the display never blanks (DPMS off) again, even after being fully idle at the password prompt for a long time.

What I expected

The idle-blank timer that normally turns the display off ~5s after the lock screen appears (via omarchy-brightness-display off) should still fire after a resume, same as it does on a normal idle-triggered lock.

Root cause (found by reading the shipped source)

In /usr/share/omarchy/shell/plugins/lock/Service.qml, the idleBlankTimer has this guard to avoid blanking the screen instantly on resume (when the timer was frozen mid-countdown by suspend):

Timer {
  id: idleBlankTimer
  interval: 5000
  repeat: false
  property double armedAt: 0
  onTriggered: {
    // A countdown frozen by suspend fires right after resume, which would
    // blank the freshly woken unlock screen under the user. Wall-clock time
    // exposes the gap: take a fresh run-up instead of blanking.
    if (Date.now() - armedAt > interval + 2000) {
      root.armBlankTimer()
      return
    }
    if (root.lockRequested && !root.authenticatingPassword) root.runBlank()
  }
}

This correctly handles the first post-resume tick. But if the Quickshell/QML event loop's timer keeps firing late by more than interval + 2000 (7s) on the next attempt too — which seems to happen reliably on my system right after resume, possibly related to amdgpu runtime power-management/DPM settling — the timer just keeps calling armBlankTimer() and re-arming instead of ever reaching root.runBlank(). The result is the screen never blanks again until real keyboard/mouse input is registered by the lock screen (which restarts the cycle via runWake()/armBlankTimer(), so it can get stuck in the same loop again).

I did not manage to capture omarchy-shell debug output live during the actual stuck state (it's intermittent, tied to being woken by someone else rather than by me), so I can't yet confirm from logs that this exact re-arm branch is what's looping. Flagging with the code-level analysis in case it's a fast recognize-and-fix for someone familiar with the timer's history, and can follow up with journalctl --user -b | grep "omarchy lock" output from a live repro if useful.

Steps to reproduce

  1. Let the machine idle-lock (or manually lock).
  2. Suspend the machine.
  3. Have someone else (or a peripheral) wake it — not via your own direct keypress on the lock screen.
  4. Observe: password screen appears and the display backlight never turns off again, indefinitely.

System details

  • Omarchy version: 4.0.3-1
  • Quickshell: 0.3.1-1
  • Kernel: 7.2.3-arch1-3 (Linux mollusc 7.2.3-arch1-3 #1 SMP PREEMPT_DYNAMIC)
  • GPU: AMD Radeon RX 9060 XT (Navi 44), amdgpu driver
  • idle.lock = 300s, idle.screensaver = 150s (defaults, unmodified in ~/.config/omarchy/shell.json)
  • systemd-logind IdleAction is unset/ignore (default) — not relevant to the bug itself, just noting actual suspend isn't idle-triggered on this box, only manual.
View raw text
## What happened

After the machine resumes from suspend (woken by someone else, not by me typing/clicking), the lock/password screen appears and stays lit indefinitely — the display never blanks (DPMS off) again, even after being fully idle at the password prompt for a long time.

## What I expected

The idle-blank timer that normally turns the display off ~5s after the lock screen appears (via `omarchy-brightness-display off`) should still fire after a resume, same as it does on a normal idle-triggered lock.

## Root cause (found by reading the shipped source)

In `/usr/share/omarchy/shell/plugins/lock/Service.qml`, the `idleBlankTimer` has this guard to avoid blanking the screen instantly on resume (when the timer was frozen mid-countdown by suspend):

```qml
Timer {
  id: idleBlankTimer
  interval: 5000
  repeat: false
  property double armedAt: 0
  onTriggered: {
    // A countdown frozen by suspend fires right after resume, which would
    // blank the freshly woken unlock screen under the user. Wall-clock time
    // exposes the gap: take a fresh run-up instead of blanking.
    if (Date.now() - armedAt > interval + 2000) {
      root.armBlankTimer()
      return
    }
    if (root.lockRequested && !root.authenticatingPassword) root.runBlank()
  }
}
```

This correctly handles the *first* post-resume tick. But if the Quickshell/QML event loop's timer keeps firing late by more than `interval + 2000` (7s) on the *next* attempt too — which seems to happen reliably on my system right after resume, possibly related to amdgpu runtime power-management/DPM settling — the timer just keeps calling `armBlankTimer()` and re-arming instead of ever reaching `root.runBlank()`. The result is the screen never blanks again until real keyboard/mouse input is registered by the lock screen (which restarts the cycle via `runWake()`/`armBlankTimer()`, so it can get stuck in the same loop again).

I did not manage to capture `omarchy-shell` debug output live during the actual stuck state (it's intermittent, tied to being woken by someone else rather than by me), so I can't yet confirm from logs that this exact re-arm branch is what's looping. Flagging with the code-level analysis in case it's a fast recognize-and-fix for someone familiar with the timer's history, and can follow up with `journalctl --user -b | grep "omarchy lock"` output from a live repro if useful.

## Steps to reproduce

1. Let the machine idle-lock (or manually lock).
2. Suspend the machine.
3. Have someone else (or a peripheral) wake it — not via your own direct keypress on the lock screen.
4. Observe: password screen appears and the display backlight never turns off again, indefinitely.

## System details

- Omarchy version: 4.0.3-1
- Quickshell: 0.3.1-1
- Kernel: 7.2.3-arch1-3 (`Linux mollusc 7.2.3-arch1-3 #1 SMP PREEMPT_DYNAMIC`)
- GPU: AMD Radeon RX 9060 XT (Navi 44), `amdgpu` driver
- `idle.lock` = 300s, `idle.screensaver` = 150s (defaults, unmodified in `~/.config/omarchy/shell.json`)
- `systemd-logind` `IdleAction` is unset/`ignore` (default) — not relevant to the bug itself, just noting actual suspend isn't idle-triggered on this box, only manual.

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.

  • Decided by agents · verified: in the audited area (lock)

The outcome (valid, duplicate, not a bug, …) is not decided yet.