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

Lock screen crash loop kills the shell and locks the user out when session-lock surface creation fails

Reported by marcaoas · filed Oct 4, 2026Closed upstream on 2026-10-04 by its own reporter marcaoas. GitHub close reason: completed. 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 screen crash loop kills the shell and locks the user out when session-lock surface creation failsrevision 1 · captured 2026-10-04 12:37 UTC via poll

What happened

When the idle lock fires while the GPU cannot allocate a new GL context, the
session-lock surface fails to initialize, quickshell aborts, and Omarchy's
stranded-lock recovery immediately re-triggers the same lock on the fresh
instance. That loops until quickshell's supervisor gives up entirely, leaving
the session behind Hyprland's failsafe lock with no shell and no unlock UI.

On my machine this locked me out of a running desktop session for ~62 minutes.
I recovered by switching to a TTY (Ctrl+Alt+F3), not through the GUI.

What I expected

A failed lock should degrade to "not locked, log a warning" — or retry a bounded
number of times with backoff. Losing the shell and the unlock UI is a strictly
worse outcome than not locking at all.

The loop

Underlying trigger: VRAM exhaustion (6 GB GTX 1060, Steam/Proton game running).
EGL returned 0x3003 (EGL_BAD_ALLOC), and the kernel logged matching
allocation failures:

kernel: [drm:nv_drm_gem_alloc_nvkms_memory_ioctl [nvidia_drm]] *ERROR*
        [GPU ID 0x00000100] Failed to allocate NVKMS memory for GEM object

That part is not Omarchy's bug, and quickshell's qFatal on a failed session-lock
surface is upstream. What is Omarchy's is that one such failure becomes seven.

The same EGL failure had already occurred harmlessly seven times over the
preceding hour (20:29, 20:44, 21:01, 21:09, 21:16, 21:21, 21:27). Each hit a
layer-shell surface, which quickshell treats as a recoverable ERROR:

ERROR: Failed to create graphics context for qs::wayland::layershell::WlrLayershell(...):
       "Failed to initialize graphics backend for OpenGL."

At 21:33:02 the idle lock fired. A session-lock surface takes the same failure
as FATAL, and the loop began:

21:33:02  DEBUG qml: omarchy idle  lock-system: lock-timeout
21:33:03  FATAL: Failed to initialize graphics backend for OpenGL.
21:33:03  ERROR: Quickshell has crashed under pid 1587443
21:33:03  ERROR: Quickshell has been restarted.
21:33:06  DEBUG qml: omarchy lock  lock-stranded: recovering
21:33:07  FATAL: Failed to initialize graphics backend for OpenGL.
21:33:07  ERROR: Quickshell crashed within 10 seconds of launching. Not restarting to avoid a crash loop.
21:33:12  DEBUG qml: omarchy lock  lock-stranded: recovering
21:33:13  FATAL: Failed to initialize graphics backend for OpenGL.
21:33:15  DEBUG qml: omarchy lock  lock-stranded: recovering
21:33:16  FATAL: Failed to initialize graphics backend for OpenGL.
21:33:20  DEBUG qml: omarchy lock  lock-stranded: recovering
21:33:21  FATAL: Failed to initialize graphics backend for OpenGL.
...
21:33:39  (7th and final abort)

Seven aborts in 36 seconds. No omarchy-shell journal output at all after
21:33:40 — the shell stayed dead until I shut down at 22:48.

Note that quickshell's own "Not restarting to avoid a crash loop" guard fires
correctly but does not help: each already-launched instance re-enters recovery
on its own before that guard can apply to it.

Cause

shell/plugins/lock/Service.qml. On startup, checkStrandedLock() (:82) runs
omarchy-hyprland-session-locked; on exit code 0 it sets strandedLock and
calls recoverStrandedLock() (:94), which calls beginLock() — the operation
that just crashed the previous instance.

The only guard is strandedLockResolved (:35), which is plain in-process
property state. Every restart begins with it false, so it cannot see that the
preceding instance died doing exactly this. There is no attempt counter, no
backoff, and no persistence across restarts.

Suggested fix

Make recovery give up rather than loop. Any of:

  • Persist an attempt count / last-attempt timestamp outside the process (e.g.

under $XDG_RUNTIME_DIR/quickshell/) and stop after 2–3 tries.
- Require a minimum uptime before recoverStrandedLock() may run, so an
instance that dies within seconds of launch cannot keep the chain going.
- On repeated failure, clear the stranded lock and surface a visible warning
instead of re-locking — an unlocked desktop with a warning beats a locked one
with no way in.

Reproduction

Needs the lock to fail at surface creation. Exhausting VRAM is one route:

  1. NVIDIA GPU with limited VRAM (6 GB GTX 1060 here), multi-monitor.
  2. Run a GPU-heavy Proton title until EGL allocations start failing — visible as

eglError: 0x3003 and Failed to create RHI (backend 2) in the shell log.
3. Leave the machine idle until the lock timeout fires.
4. quickshell aborts, recovers, aborts, repeatedly — then the shell is gone and
the screen cannot be unlocked.

Any condition that reliably fails session-lock surface creation should do;
the VRAM angle is just how I hit it.

System

Omarchy:       4.0.4-1 (stable channel)
quickshell:    0.3.1-1
qt6-base:      6.11.2-3
hyprland:      0.56.2-2
nvidia-580xx:  580.178.04-1.1
kernel:        linux 7.2.3.arch1-3 (running 7.2.5-3-omarchy)
GPU:           NVIDIA GeForce GTX 1060 6GB (10de:1c03)
Monitors:      3840x2160@120 (scale 1.5) + 1920x1080@144
Packages last upgraded: 2026-09-16 (17 days before the crash — not a regression)

omarchy debug is not available in 4.0.4, so the above was collected manually
via omarchy version, omarchy version channel/pkgs, and pacman -Q.

Core dumps for all seven aborts, and quickshell's own crash reports under
~/.cache/quickshell/crashes/, are available if useful.


Filed by Claude Opus 5 via Claude Code.

View raw text
## What happened

When the idle lock fires while the GPU cannot allocate a new GL context, the
session-lock surface fails to initialize, quickshell aborts, and Omarchy's
stranded-lock recovery immediately re-triggers the same lock on the fresh
instance. That loops until quickshell's supervisor gives up entirely, leaving
the session behind Hyprland's failsafe lock with **no shell and no unlock UI**.

On my machine this locked me out of a running desktop session for ~62 minutes.
I recovered by switching to a TTY (Ctrl+Alt+F3), not through the GUI.

## What I expected

A failed lock should degrade to "not locked, log a warning" — or retry a bounded
number of times with backoff. Losing the shell *and* the unlock UI is a strictly
worse outcome than not locking at all.

## The loop

Underlying trigger: VRAM exhaustion (6 GB GTX 1060, Steam/Proton game running).
EGL returned `0x3003` (`EGL_BAD_ALLOC`), and the kernel logged matching
allocation failures:

```
kernel: [drm:nv_drm_gem_alloc_nvkms_memory_ioctl [nvidia_drm]] *ERROR*
        [GPU ID 0x00000100] Failed to allocate NVKMS memory for GEM object
```

That part is not Omarchy's bug, and quickshell's `qFatal` on a failed session-lock
surface is upstream. What *is* Omarchy's is that one such failure becomes seven.

The same EGL failure had already occurred harmlessly seven times over the
preceding hour (20:29, 20:44, 21:01, 21:09, 21:16, 21:21, 21:27). Each hit a
*layer-shell* surface, which quickshell treats as a recoverable `ERROR`:

```
ERROR: Failed to create graphics context for qs::wayland::layershell::WlrLayershell(...):
       "Failed to initialize graphics backend for OpenGL."
```

At 21:33:02 the idle lock fired. A *session-lock* surface takes the same failure
as `FATAL`, and the loop began:

```
21:33:02  DEBUG qml: omarchy idle  lock-system: lock-timeout
21:33:03  FATAL: Failed to initialize graphics backend for OpenGL.
21:33:03  ERROR: Quickshell has crashed under pid 1587443
21:33:03  ERROR: Quickshell has been restarted.
21:33:06  DEBUG qml: omarchy lock  lock-stranded: recovering
21:33:07  FATAL: Failed to initialize graphics backend for OpenGL.
21:33:07  ERROR: Quickshell crashed within 10 seconds of launching. Not restarting to avoid a crash loop.
21:33:12  DEBUG qml: omarchy lock  lock-stranded: recovering
21:33:13  FATAL: Failed to initialize graphics backend for OpenGL.
21:33:15  DEBUG qml: omarchy lock  lock-stranded: recovering
21:33:16  FATAL: Failed to initialize graphics backend for OpenGL.
21:33:20  DEBUG qml: omarchy lock  lock-stranded: recovering
21:33:21  FATAL: Failed to initialize graphics backend for OpenGL.
...
21:33:39  (7th and final abort)
```

Seven aborts in 36 seconds. No `omarchy-shell` journal output at all after
21:33:40 — the shell stayed dead until I shut down at 22:48.

Note that quickshell's own "Not restarting to avoid a crash loop" guard fires
correctly but does not help: each *already-launched* instance re-enters recovery
on its own before that guard can apply to it.

## Cause

`shell/plugins/lock/Service.qml`. On startup, `checkStrandedLock()` (:82) runs
`omarchy-hyprland-session-locked`; on exit code 0 it sets `strandedLock` and
calls `recoverStrandedLock()` (:94), which calls `beginLock()` — the operation
that just crashed the previous instance.

The only guard is `strandedLockResolved` (:35), which is plain in-process
property state. Every restart begins with it `false`, so it cannot see that the
preceding instance died doing exactly this. There is no attempt counter, no
backoff, and no persistence across restarts.

## Suggested fix

Make recovery give up rather than loop. Any of:

- Persist an attempt count / last-attempt timestamp outside the process (e.g.
  under `$XDG_RUNTIME_DIR/quickshell/`) and stop after 2–3 tries.
- Require a minimum uptime before `recoverStrandedLock()` may run, so an
  instance that dies within seconds of launch cannot keep the chain going.
- On repeated failure, clear the stranded lock and surface a visible warning
  instead of re-locking — an unlocked desktop with a warning beats a locked one
  with no way in.

## Reproduction

Needs the lock to fail at surface creation. Exhausting VRAM is one route:

1. NVIDIA GPU with limited VRAM (6 GB GTX 1060 here), multi-monitor.
2. Run a GPU-heavy Proton title until EGL allocations start failing — visible as
   `eglError: 0x3003` and `Failed to create RHI (backend 2)` in the shell log.
3. Leave the machine idle until the lock timeout fires.
4. quickshell aborts, recovers, aborts, repeatedly — then the shell is gone and
   the screen cannot be unlocked.

Any condition that reliably fails session-lock surface creation should do;
the VRAM angle is just how I hit it.

## System

```
Omarchy:       4.0.4-1 (stable channel)
quickshell:    0.3.1-1
qt6-base:      6.11.2-3
hyprland:      0.56.2-2
nvidia-580xx:  580.178.04-1.1
kernel:        linux 7.2.3.arch1-3 (running 7.2.5-3-omarchy)
GPU:           NVIDIA GeForce GTX 1060 6GB (10de:1c03)
Monitors:      3840x2160@120 (scale 1.5) + 1920x1080@144
Packages last upgraded: 2026-09-16 (17 days before the crash — not a regression)
```

`omarchy debug` is not available in 4.0.4, so the above was collected manually
via `omarchy version`, `omarchy version channel/pkgs`, and `pacman -Q`.

Core dumps for all seven aborts, and quickshell's own crash reports under
`~/.cache/quickshell/crashes/`, are available if useful.

---

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

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.

No decision has been recorded yet.