Skip to content

Intermittent 'send_key_state: key not found' on Super+V/C/X clipboard shortcuts #7027

Open

Description

@Louis454545

Summary

Pressing Super+V (universal paste), and sometimes Super+C / Super+X, intermittently shows a Hyprland Lua runtime error:

Runtime error in lua:
=[C]:-1: send_key_state: key not found

Paste/copy/cut may fail when the error appears.

Root cause

Omarchy's clipboard bindings in default/hypr/bindings/clipboard.lua call hl.dsp.send_key_state immediately when the bind fires. The bind itself uses Super as a modifier (SUPER + V), so Super is still held when Hyprland tries to resolve the synthetic key (CTRL+V, SHIFT+Insert, etc.).

This matches a known Hyprland input bug where send_key_state / send_shortcut key lookup can fail while bind modifiers are still depressed:

Even on Hyprland 0.56.2 (which includes PR #15401), the error still reproduces intermittently.

Steps to reproduce

  1. Use default Omarchy clipboard bindings (Super+V paste).
  2. Paste repeatedly in different apps (terminal and non-terminal).
  3. Observe intermittent Hyprland notification: send_key_state: key not found.

Expected

Super+V should always paste without Lua runtime errors.

Actual

Intermittent send_key_state: key not found error; paste may not happen.

Environment

  • Omarchy: 4.0.0-1
  • Hyprland: 0.56.2-1
  • Keyboard layout: fr (AZERTY)
  • Bindings file: default/hypr/bindings/clipboard.lua

Suggested fix

Delay the synthetic key dispatch until after Super is released, e.g. wrap the down/up send_key_state calls in an hl.timer (~80ms oneshot) before sending down. This is the same pattern already used for the up event, extended to avoid the race with the held Super modifier.

Workaround (user config)

Override in ~/.config/hypr/bindings.lua by unbinding SUPER + C/V/X and rebinding with a delayed send_key_state helper.

Activity

  1. assada commented on Aug 17, 2026

    @assada

    Adding a deterministic reproduction of this error that has a different root cause than the held-SUPER race — it may also explain the intermittency reported here.

    Repro: any non-Latin keyboard layout

    -- ~/.config/hypr/input.lua
    hl.config({ input = { kb_layout = "us,ua", kb_options = "grp:caps_toggle" } })

    Switch to the second (Ukrainian) group and press SUPER+C / SUPER+V / SUPER+X in any non-terminal window (Chromium, Obsidian, Telegram — all reproduce 100% of the time):

    Runtime error in lua:
    =[C]:-1: send_key_state: key not found
    

    In a terminal the same keys work fine. That is not a terminal-vs-GUI difference — it falls straight out of default/hypr/bindings/clipboard.lua:

    o.bind("SUPER + C", "Universal copy", universal_clipboard_shortcut("CTRL", "C", "CTRL", "Insert"))
    o.bind("SUPER + V", "Universal paste", universal_clipboard_shortcut("CTRL", "V", "SHIFT", "Insert"))

    The terminal branch sends Insert, which exists in every xkb group. Non-terminal windows get the letter keys, which do not.

    Root cause

    send_key_state resolves the key name against the currently active xkb group only — src/config/lua/bindings/LuaBindingsDispatchers.cpp#L354-L398:

    xkb_state_update_mask(ks, 0, 0, 0, 0, 0, KB->m_modifiersState.group);   // <- active group only
    
    for (xkb_keycode_t kc = keycode_min; kc <= keycode_max; ++kc) {
        xkb_keysym_t sym = xkb_state_key_get_one_sym(ks, kc);
        if (sym == KEYSYM) { ... }
    }
    
    if (!keycode)
        return std::unexpected("key not found");

    And in the ua group there simply is no c / v / x keysym to find:

    $ xkbcli compile-keymap --layout "us,ua"
    key <AB03> { symbols[1] = [ c, C ],
                 symbols[2] = [ Cyrillic_es, Cyrillic_ES, copyright, NoSymbol ] };
    key <AB04> { symbols[1] = [ v, V ],
                 symbols[2] = [ Cyrillic_em, Cyrillic_EM ] };
    

    So the lookup fails before any key is sent, and copy/paste/cut silently do nothing.

    Why it can look intermittent

    A few lines above, the resolved keycode is memoised:

    const auto KEYPAIRSTRING = std::format("{}{}", rc<uintptr_t>(KB.get()), key);
    if (g_pKeybindManager->m_keyToCodeCache.contains(KEYPAIRSTRING))
        return g_pKeybindManager->m_keyToCodeCache[KEYPAIRSTRING];

    The cache key is keyboard pointer + key name — the layout group is not part of it. So whether SUPER+C works depends on which group was active the first time it was pressed after the keyboard object was created: resolve it once under a Latin layout and it keeps working under any layout, until the cache is dropped (config reload, keyboard re-created, hyprctl reload, monitor/input hotplug). That ordering dependency is a plausible source of the "sometimes it works, sometimes it doesn't" behaviour, and it is worth ruling out separately from the held-SUPER race.

    (For fr/AZERTY, c/v/x do exist in the layout, so the original report here is probably a different trigger hitting the same code path.)

    Workaround

    Raw keycodes skip the keysym lookup entirely (resolveKeycode handles code: before touching xkb), so this is layout-independent:

    o.bind("SUPER + C", "Universal copy",  universal_clipboard_shortcut("CTRL", "code:54", "CTRL", "Insert"))
    o.bind("SUPER + V", "Universal paste", universal_clipboard_shortcut("CTRL", "code:55", "SHIFT", "Insert"))
    o.bind("SUPER + X", "Universal cut",   send_shortcut_once("CTRL", "code:53"))

    code:54 / 55 / 53 are <AB03> / <AB04> / <AB02> — the physical C / V / X keys. Confirmed working here in both groups.

    If that looks acceptable, clipboard.lua could just use keycodes; the more general fix would be for resolveKeycode to fall back to scanning the other layout groups (and to include the group in m_keyToCodeCache's key).

    Environment

    • Omarchy 4.0.0-1, Hyprland 0.56.2-1, Arch, kb_layout = "us,ua", kb_options = "grp:caps_toggle"
  2. shashwat-raj-420 commented on Aug 19, 2026

    @shashwat-raj-420

    I’m also experiencing this issue, but on a US keyboard layout.

    Environment:

    • Omarchy: 4.0.0-1
    • Hyprland: 0.56.2-1
    • Keyboard layout: us
    • Laptop keyboard
    • VS Code integrated terminal is affected

    With the default Universal Clipboard bindings:

    • Super+C does not copy correctly
    • Super+V does not paste correctly
    • Ctrl+Shift+C/V work normally in the VS Code integrated terminal

    I also tested the suggested ~80ms delayed send_key_state workaround from this issue, but it does not resolve the problem for me.

    One useful finding: this direct Hyprland command successfully pastes into the VS Code integrated terminal:

    hyprctl eval 'hl.dispatch(hl.dsp.send_shortcut({ mods = "CTRL SHIFT", key = "V", window = "activewindow" }))'

    So VS Code's terminal and the clipboard itself are working; the problem appears to be specifically with the Universal Clipboard binding/injection path.

    My personal Super+C/V overrides were removed during testing, so this reproduces with the default Omarchy bindings.

    Unlike the original report, I am using the us keyboard layout, so this may not be limited to non-US/AZERTY layouts.

  3. omarchybot commented on Oct 8, 2026

    @omarchybot
    Collaborator

    I looked at this against current quattro and Hyprland 0.56.2's source, and reproduced it on a clean Omarchy worker running Hyprland 0.56.2.

    What produces send_key_state: key not found. Hyprland turns the key name (V) into a keycode by scanning the keymap of whichever keyboard last sent input, in that keyboard's active layout group only (resolveKeycode). It fails in two situations I reproduced on the worker:

    • A non-Latin layout group is active, as @assada described. With kb_layout = "us,ua" and the Ukrainian group active, c, v, x and a all fail, and Cyrillic_es resolves. Successful lookups are cached by keyboard and key name, not by group. So a letter that was first used under the Latin group keeps working after switching, and one used for the first time under the other group fails. That is why it looks intermittent.
    • The last keyboard to send input is a virtual keyboard whose keymap lacks the letter. While wtype held its virtual keyboard (it typed only q), resolving z and y failed on a plain us layout, and they worked again once it exited.

    The held-Super explanation in the original report doesn't hold. The lookup builds a fresh xkb state with all modifiers cleared and keeps only the group (line 384), so a held Super cannot affect it. That matches the report here that the 80 ms delay didn't help. With a single fr layout, C/V/X resolve normally. So the trigger on the original machine is still unknown. The source allows it if the keyboard Hyprland treats as current is not the one you typed on: an input method forwarding keys, or an input-sharing or remote tool (Input Leap, Deskflow, lan-mouse, wayvnc and the like). @Louis454545, it would help to know whether you use any of those, whether you have more than one layout configured, and the Keyboards section of hyprctl devices taken right after the error appears.

    Not fixed on quattro. Since 4.0.0, terminals get Ctrl+Shift+C/V instead of Ctrl/Shift+Insert. That means terminals are now affected by the non-Latin case too, where before they were immune.

    Fix in review. #13007 resolves each letter against the primary layout and sends a raw code:N, which Hyprland accepts without the lookup above. That avoids both mechanisms. If the resolution fails, it falls back to the named key, which can still hit this error. #7371 and #12570 are later reports of the non-Latin case. I haven't linked #13007 to close this issue, because the original French-layout trigger isn't established.

    The VS Code integrated terminal report is a different bug. It doesn't involve this error. VS Code isn't tagged as a terminal, so Super+C/V send Ctrl+C/V, which VS Code's integrated terminal on Linux doesn't use for copy and paste by default (it uses Ctrl+Shift+C/V, which you found working). That's the same shape as #13682.

    Codex Medium gave a second opinion. It agreed with the mechanisms, that held Super is ruled out, and that the VS Code case is separate. It also pointed out the fallback in #13007 described above. It could read this review's working notes, so its agreement isn't fully independent. This waits on the maintainer's decision on #13007, and on the details above for the original French-layout case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions