GitoxideLabs/gitoxide · error
command shortcuts always contain a leaf key
Error message
command shortcuts always contain a leaf key
What it means
This is a Rust `expect` panic in `Command::key()` (gix-tix/src/command_menu.rs:101). The code derives a command's keybinding by taking the last character (`chars().next_back()`) of the human-readable shortcut string. The library authors assert that every command's shortcut contains at least one 'leaf' key character; the panic fires when a shortcut string is empty.
Solutions
- Set a non-empty `shortcut` for every command pushed in `commands()`; never pass an empty string literal.
- Validate at construction time: make `Command::new` reject or fall back on empty shortcuts so the invariant fails fast with a clear message.
- If shortcuts can come from external data, guard the accessor: `self.shortcut.chars().next_back().unwrap_or('\0')` or return `Option<char>` and handle the None case in the caller.
Example fix
// before
pub(crate) fn key(&self) -> char {
self.shortcut.chars().next_back().expect("command shortcuts always contain a leaf key")
}
// after
pub(crate) fn key(&self) -> Option<char> {
self.shortcut.chars().next_back()
}
// or keep the signature and validate at the construction site:
// assert!(!shortcut.is_empty(), "command shortcut must have a leaf key"); Defensive patterns
Strategy: validation
Validate before calling
// Before registering/using a Command:
fn valid_command(c: &Command) -> bool {
!c.shortcut.is_empty() && c.shortcut.chars().next_back().is_some()
}
assert!(valid_command(&cmd), "command {:?} has an empty shortcut", cmd.id); Type guard
fn leaf_key(c: &Command) -> Option<char> {
c.shortcut.chars().next_back()
} Prevention
- Never construct `Command` with an empty shortcut; use a compile-time constant or a constructor that validates.
- Add a unit test asserting every command from `commands()` has a non-empty shortcut.
- If shortcuts come from config/translations, validate them at load time.
When it happens
Trigger: Calling `Command::key()` on a `Command` whose `shortcut` field is an empty string. This happens if a command is constructed with `shortcut: ""` in `commands()` in gix-tix/src/command_menu.rs, e.g. via the `push` closure, or if a shortcut is built dynamically (e.g. from config or locale data) and ends up empty.
Common situations: Developers adding a new menu command and forgetting to fill in the shortcut, or building shortcuts programmatically from translated/config-driven key names that resolve to an empty string. Since `next_back()` returns `Option<char>`, the crash surfaces only when the accessor runs, not at construction.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- parser must have set some object value
- successful iteration has outcome
- valid ASCII
- every parent is set only once
- attr itself
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/27f23dea1171f46c.
Report an issue: GitHub.
Appendix: source
Thrown at gix-tix/src/command_menu.rs:101
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct Command {
pub(crate) id: CommandId,
pub(crate) group: CommandGroup,
pub(crate) row: usize,
pub(crate) label: &'static str,
pub(crate) shortcut: &'static str,
pub(crate) active: bool,
pub(crate) action: Action,
}
impl Command {
pub(crate) fn key(&self) -> char {
self.shortcut
.chars()
.next_back()
.expect("command shortcuts always contain a leaf key")
}
}
pub(crate) fn commands(app: &App, decorations: &Decorations, has_verifiable_signatures: bool) -> Vec<Command> {
let mut out = Vec::with_capacity(35);
let mut push = |id, group, row, label, shortcut, active, action| {
out.push(Command {
id,
group,
row,
label,
shortcut,
active,
action,
});
};
let (date_label, date_active) = match app.date_mode {View on GitHub (pinned to e73179060b)