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

  1. Set a non-empty `shortcut` for every command pushed in `commands()`; never pass an empty string literal.
  2. Validate at construction time: make `Command::new` reject or fall back on empty shortcuts so the invariant fails fast with a clear message.
  3. 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

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


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)