linebender/druid · error

unrecognised key event

Error message

unrecognised key event

What it means

The Wayland keyboard handler panics when a key event's `KeyState` is neither `Released` nor `Pressed`. The code maps known states to `KeyState::Up`/`Down` and treats any other value as unrecoverable because it cannot be interpreted.

Solutions

  1. Update the wayland client library so unknown enum values are handled explicitly
  2. Patch the handler to log and skip unknown key states instead of panicking
  3. Verify compositor compatibility / protocol version negotiation

Example fix

// before
_ => panic!("unrecognised key event"),

// after
other => {
    tracing::warn!("unrecognised key state: {:?}", other);
    return;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Can't validate remote enum values; guard at the handler boundary by matching exhaustively before processing

Type guard

fn is_known_key_state(s: wl_keyboard::KeyState) -> bool {
    matches!(s, wl_keyboard::KeyState::Released | wl_keyboard::KeyState::Pressed)
}

Try / catch

std::panic::catch_unwind(AssertUnwindSafe(|| process_key(evt)))
  .unwrap_or_else(|_| log::warn!("skipped unknown key state"));

Prevention

When it happens

Trigger: A `wl_keyboard::KeyState` value arrives from the compositor that is not `Released` or `Pressed` (unknown enum value), reaching `keystroke` processing via `consume`.

Common situations: A compositor or wayland protocol extension emitting a new/unknown key state; protocol desync after a malformed event.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10). Data as JSON: /api/errors/143b6d9f13d0c05f. Report an issue: GitHub.

Appendix: source

Thrown at druid-shell/src/backend/wayland/keyboard.rs:116

                if last.key != current.key {
                    return Some(last.clone());
                }
                None
            }
        }
    }

    fn keystroke<'a>(&'a mut self, keystroke: &'a CachedKeyPress) {
        let keystate = match keystroke.state {
            wl_keyboard::KeyState::Released => {
                self.replace_last_key_press(self.release_last_key_press(keystroke));
                KeyState::Up
            }
            wl_keyboard::KeyState::Pressed => {
                self.replace_last_key_press(Some(keystroke.repeat()));
                KeyState::Down
            }
            _ => panic!("unrecognised key event"),
        };

        let mut event = self.xkb_state.borrow_mut().as_mut().unwrap().key_event(
            keystroke.key,
            keystate,
            keystroke.repeat,
        );
        event.mods = self.xkb_mods.get();

        if let Err(cause) = keystroke.queue.send(event) {
            tracing::error!("failed to send Druid key event: {:?}", cause);
        }
    }

    fn consume(
        &mut self,
        seat: u32,
        event: wl_keyboard::Event,

View on GitHub (pinned to 0f8b1195e4)