Repository navigation
A user's own binds in ~/.config/hypr/bindings.lua never reach the keybindings menu's Lua scan #13790
Description
What happens
omarchy-menu-keybindings keeps its own Lua scan of the user's config, because Hyprland reports every Lua bind as dispatcher __lua with no arg and no id. The scan dies partway through the shipped config, and the pcall wrapped around it discards the error, so nothing surfaces.
The result is that no bind in ~/.config/hypr/bindings.lua is ever scanned. A user's own binds get no dispatcher recovery and no id in the keybindings menu.
Why
Two things line up:
default/hypr/omarchy.lua:18isrequire("default.hypr.qconsole"). Under the scan'snoopstub,hl.get_workspacereturns a stub table, so indefault/hypr/qconsole.lua:123themon.scale > 0test compares a table with a number and throws.config/hypr/hyprland.luarequiresdefault.hypr.omarchyat line 14 andhypr.bindingsat line 21. The throw at step 1 unwinds past line 21.
The 229 default binds registered before line 18 do survive, which is why the menu looks fine on a stock install and why this has gone unnoticed.
Reproduce
# extract the scan from the menu, verbatim
sed -n "/^ lua <<'LUA'\$/,/^LUA\$/p" bin/omarchy-menu-keybindings | sed '1d;$d' >/tmp/scan.lua
# a stock config plus one personal bind, where the comments in the shipped
# bindings.lua tell you to put it
mkdir -p /tmp/h/.config && cp -r config/hypr /tmp/h/.config/hypr
echo 'o.bind("SUPER + ALT + P", "My own bind", "true")' >>/tmp/h/.config/hypr/bindings.lua
env -i PATH="$PATH" HOME=/tmp/h OMARCHY_PATH="$PWD" DEBUG=1 lua /tmp/scan.lua[DEBUG] lua bind scan failed: .../default/hypr/qconsole.lua:123: attempt to compare number with table
229 lines on stdout, and My own bind is not one of them. Move require("default.hypr.helpers") and require("hypr.bindings") ahead of require("default.hypr.omarchy") in hyprland.lua and it becomes 230 lines with My own bind present, which confirms the load order is what is doing it.
Why it matters beyond the id
A user who renames or translates a bind description in ~/.config/hypr/bindings.lua gets no id for it, so the menu falls back to the description. Since the menu's row pairing and its sort order both key on a name, a renamed bind loses the row it shared and the tier it belonged to. Measured on linyiru:menu-sort-by-bind-id (the follow-up to #12557, which moves those two decisions onto the id), with two chords declaring the same id = "Close window" and a translated description:
# both binds in ~/.config/hypr/bindings.lua, shipped load order
SUPER ALT + Q → 關閉視窗
SUPER ALT + W → 關閉視窗
# same two binds, load order changed so the scan reaches them
SUPER ALT + W / SUPER ALT + Q → 關閉視窗
So this gates the bind-id work: the ids are threaded correctly, and a personal config still cannot use them, because the scan never reads the file they are declared in.
Scope
Pre-existing and unrelated to bind ids. I am reporting rather than patching because the fix is a judgement call I would rather not make alone: either the scan's stub grows enough shape for qconsole.lua to survive it, or the scan stops depending on the shipped config loading cleanly, or pcall stops being allowed to fail silently. Happy to implement whichever you prefer.
Verified 2026-09-29 on Arch, Lua 5.5.1, at 647b4a21.
🤖 Generated with Claude Code
Activity
manuaudio commentedon Sep 29, 2026
Open PR #13276 ("keep the Lua bind scan alive past qconsole.lua") targets this same failure: the scan dying in
qconsole.luabefore it reaches~/.config/hypr/bindings.lua. #12916 (contain the Lua bind scan) is related. Your repro with the personalSUPER + ALT + Pbind would make a good check for whichever lands.linyiru commentedon Sep 29, 2026
Duplicate of #13276. Closing, and thank you @manuaudio for the fast redirect.
@playGitboy's report is the better one: same error at the same line, the same "dies after the defaults and before
require("hypr.bindings")" mechanism, plus measurement I did not have (22 of 260 cached rows losing their dispatcher, all of them frombindings.lua) and a downstream consequence I had not thought of, where a virtual keyboard reading the records file falls back towtype, which Hyprland does not route into its own binds, so the key silently does nothing. #12916 is the other half of the same area, containing the scan rather than teaching the stub to survive it.I should not have opened this. I had searched this repo's prior art for exactly this defect on 2026-09-28, found the cluster of open PRs around that scan, and retracted a public promise to file it on those grounds. Filing it today means I acted on that conclusion without re-running the search. Apologies for the noise.
Taking up your suggestion about the repro, @manuaudio: I turned it into an assertion in the existing
test/shell.d/keybindings-menu-test.shharness and checked that it discriminates,not okat647b4a21andokat #13276's head14f7e955. Since llstrk's review of #13276 lists a missing regression test, I have offered it there rather than keeping it here.🤖 Generated with Claude Code