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.
omarchy-menu-keybindings: mock 'noop' table causes unbounded infinite loop and 100% CPU when config iterates with ipairs
Reported by LoupiBe · filed Sep 16, 2026 · open at source
R-1816 is the earliest report of this defect — filed Aug 15, 2026, open upstream. This report (filed Sep 16, 2026) describes the same defect, so it is folded under it in the inbox.
Decided by agents · verified· Oct 8, 2026
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?
- 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?
- Decided by agents and verified by a second, independent agent — see the decision.
Original report
System details
Intel Core i7-8665U, Intel UHD Graphics 620, Omarchy 4.0.4-1
What's wrong?
Description
When pressing SUPER + K (or running omarchy menu keybindings / omarchy-menu-keybindings), if the user's Hyprland Lua configuration (or any module it requires) uses ipairs() on a function call or table that falls back to the mock noop object (for example, ipairs(hl.get_windows() or {})), the subshell Lua process enters an infinite loop, never exits, and spins at 100% CPU.
Each time SUPER + K is pressed, another un-reaped lua process is spawned and pegs a CPU core permanently.
Steps to Reproduce
- In
~/.config/hypr/hyprland.lua(or a required module), add any standard Lua loop that iterates over a mockable Hyprland API, such as:
for _, w in ipairs(hl.get_windows() or {}) do
-- window handling logic
end (Note: This is completely valid Lua inside the real Hyprland compositor).
2. Clear the keybindings cache:
rm -f ~/.cache/omarchy/keybindings-*.records- Press
SUPER + Kor execute:
omarchy-menu-keybindings --print- Observe that the command never completes, and
ps aux | grep luashows aluaprocess consuming 100% CPU.
Root Cause
In /usr/share/omarchy/bin/omarchy-menu-keybindings:
local noop
noop = setmetatable({}, {
__index = function()
return noop
end,
__call = function()
return noop
end,
})
hl = setmetatable({
dsp = dsp_proxy("hl.dsp"),
bind = function(keys, bind_dispatcher, opts)
-- ...
end,
get_config = function()
return nil
end,
}, {
__index = function()
return noop
end,
})omarchy-menu-keybindings parses user keybindings by executing dofile("~/.config/hypr/hyprland.lua") in a standalone lua subshell.
To avoid crashes on unhandled Hyprland APIs, it falls back to a recursive noop mock.
However, in Lua, ipairs(t) iterates sequentially (t[1], t[2], t[3], ...) until the table returns nil. Because noop's __index returns noop (which is truthy) for all keys, noop[1], noop[2], etc. are never nil. As a result, ipairs(noop) becomes an infinite loop.
Proposed Solution
In /usr/share/omarchy/bin/omarchy-menu-keybindings, update noop so that numeric index lookups return nil:
local noop
noop = setmetatable({}, {
__index = function(self, key)
if type(key) == "number" then
return nil
end
return noop
end,
__call = function()
return noop
end,
__len = function()
return 0
end,
})Additionally, common query functions like hl.get_windows, hl.get_monitors, hl.get_workspaces can be explicitly stubbed on hl to return {}:
get_windows = function() return {} end,
get_monitors = function() return {} end,
get_workspaces = function() return {} end,View raw text
### System details
Intel Core i7-8665U, Intel UHD Graphics 620, Omarchy 4.0.4-1
### What's wrong?
#### Description
When pressing `SUPER + K` (or running `omarchy menu keybindings` / `omarchy-menu-keybindings`), if the user's Hyprland Lua configuration (or any module it `require`s) uses `ipairs()` on a function call or table that falls back to the mock `noop` object (for example, `ipairs(hl.get_windows() or {})`), the subshell Lua process enters an infinite loop, never exits, and spins at 100% CPU.
Each time `SUPER + K` is pressed, another un-reaped `lua` process is spawned and pegs a CPU core permanently.
#### Steps to Reproduce
1. In `~/.config/hypr/hyprland.lua` (or a required module), add any standard Lua loop that iterates over a mockable Hyprland API, such as:
```lua
for _, w in ipairs(hl.get_windows() or {}) do
-- window handling logic
end
```
*(Note: This is completely valid Lua inside the real Hyprland compositor).*
2. Clear the keybindings cache:
```bash
rm -f ~/.cache/omarchy/keybindings-*.records
```
3. Press `SUPER + K` or execute:
```bash
omarchy-menu-keybindings --print
```
4. Observe that the command never completes, and `ps aux | grep lua` shows a `lua` process consuming 100% CPU.
#### Root Cause
In `/usr/share/omarchy/bin/omarchy-menu-keybindings`:
```lua
local noop
noop = setmetatable({}, {
__index = function()
return noop
end,
__call = function()
return noop
end,
})
hl = setmetatable({
dsp = dsp_proxy("hl.dsp"),
bind = function(keys, bind_dispatcher, opts)
-- ...
end,
get_config = function()
return nil
end,
}, {
__index = function()
return noop
end,
})
```
`omarchy-menu-keybindings` parses user keybindings by executing `dofile("~/.config/hypr/hyprland.lua")` in a standalone `lua` subshell.
To avoid crashes on unhandled Hyprland APIs, it falls back to a recursive `noop` mock.
However, in Lua, `ipairs(t)` iterates sequentially (`t[1]`, `t[2]`, `t[3]`, ...) until the table returns `nil`. Because `noop`'s `__index` returns `noop` (which is truthy) for **all** keys, `noop[1]`, `noop[2]`, etc. are never `nil`. As a result, `ipairs(noop)` becomes an infinite loop.
#### Proposed Solution
In `/usr/share/omarchy/bin/omarchy-menu-keybindings`, update `noop` so that numeric index lookups return `nil`:
```lua
local noop
noop = setmetatable({}, {
__index = function(self, key)
if type(key) == "number" then
return nil
end
return noop
end,
__call = function()
return noop
end,
__len = function()
return 0
end,
})
```
Additionally, common query functions like `hl.get_windows`, `hl.get_monitors`, `hl.get_workspaces` can be explicitly stubbed on `hl` to return `{}`:
```lua
get_windows = function() return {} end,
get_monitors = function() return {} end,
get_workspaces = function() return {} end,
```
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
- Duplicate ofR-1816omarchy-menu-keybindings hangs forever when a user Lua config iterates hl.get_monitors()· decided by agents · verified
- Fixed bypr/14128· confirmed
- Fixed bypr/12712· confirmed
- Fixed bypr/7564· confirmed
- Fixed bypr/13276· confirmed
- Fixed bypr/11733· confirmed
- Fixed bypr/12155· 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.