linebender/druid · critical
keyboard event processing failed
Error message
keyboard event processing failed
What it means
After initializing the keyboard event loop, the Wayland backend runs `eventloop.dispatch(Duration::from_secs(60), ...)` in a loop-ish dispatch call; a dispatch returning Err (internal calloop error, dispatcher callback failure, or io error on the event source) is unwrapped with expect('keyboard event processing failed'), panicking the keyboard thread and ending key input/repeat handling.
Solutions
- Update druid-shell and calloop — dispatch error handling in the wayland keyboard backend has been improved in newer versions.
- Check for panics/errors inside the keyboard dispatch callback; fix the underlying source error.
- Verify the wayland connection remains alive; reconnect handling (compositor restart) may be required.
- In a patched build, replace expect with a logged error so keyboard failure degrades gracefully instead of killing the thread.
- Reproduce with WAYLAND_DEBUG=1 to identify which event/source fails and report upstream.
Example fix
// before
eventloop.dispatch(std::time::Duration::from_secs(60), &mut (signal, Keyboard::default()), |_ignored| {})
.expect("keyboard event processing failed");
// after
if let Err(e) = eventloop.dispatch(std::time::Duration::from_secs(60), &mut (signal, Keyboard::default()), |_ignored| {}) {
tracing::error!("keyboard event dispatch failed: {e}");
} Defensive patterns
Strategy: try-catch
Try / catch
// wrap dispatch instead of expect:
match eventloop.dispatch(timeout, &mut state, |_ignored| {}) {
Ok(()) => {}
Err(e) => log::error!("keyboard dispatch failed: {e}"), // log and continue/reconnect
} Prevention
- Avoid panicking inside keyboard dispatch callbacks; route errors to logging.
- Handle compositor restarts / wayland connection loss explicitly.
- Keep calloop and druid-shell versions current and compatible.
- Reproduce odd input failures with WAYLAND_DEBUG=1 before they crash the loop.
When it happens
Trigger: calloop dispatch returning Err during keyboard event processing: the inserted rx source or the key-repeat timer fails, the wayland connection's rx channel errors, or the dispatcher state (LoopSignal, Keyboard) is corrupted; also raised if dispatch is called on an already-signaled/dead loop.
Common situations: Wayland compositor restarts or connection drops mid-session; key-repeat timer misbehaving after rapid key events; panics inside the dispatched callback propagating out as dispatch errors; long-running sessions hitting resource exhaustion.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- failed to initialize the keyboard event loop!
- unexpected wayland event
- failed to initialize the displays event loop!
- unrecognised key event
- only xkb keymap supported for now
AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10).
Data as JSON: /api/errors/834b57bdfc304a26.
Report an issue: GitHub.
Appendix: source
Thrown at druid-shell/src/backend/wayland/keyboard.rs:279
// generate repeat keypresses.
handle
.insert_source(repeat, |event, timer, state| {
timer.add_timeout(state.1.repeat.rate, event.clone());
state.1.keystroke(&event);
})
.unwrap();
tracing::debug!("keyboard event loop initiated");
eventloop
.run(
std::time::Duration::from_secs(60),
&mut (signal, Keyboard::default()),
|_ignored| {
tracing::trace!("keyboard event loop idle");
},
)
.expect("keyboard event processing failed");
tracing::debug!("keyboard event loop completed");
});
state
}
}
struct ModMap(u32, Modifiers);
impl ModMap {
fn merge(self, m: Modifiers, mods: u32, locked: u32) -> Modifiers {
if self.0 & mods == 0 && self.0 & locked == 0 {
return m;
}
m | self.1
}
}View on GitHub (pinned to 0f8b1195e4)