helix-editor/helix · error · anyhow::Error
Invalid key modifier '{}-'
Error message
Invalid key modifier '{}-' What it means
After the key code is consumed, each remaining '-'-separated token must be a modifier: "S" (shift), "A" (alt), "C" (control), or "Meta"/"Cmd"/"Win" (super). Any other token fails with "Invalid key modifier '{token}-'". Long-form words like Ctrl, Shift, Alt are deliberately not accepted.
Source
Thrown at helix-view/src/input.rs:426
} else {
let suggestion = format!("{}-{}", s.trim_end_matches('-'), keys::MINUS);
return Err(anyhow!(
"Key '-' cannot be used with modifiers, use '{}' instead",
suggestion
));
}
}
invalid => return Err(anyhow!("Invalid key code '{}'", invalid)),
};
let mut modifiers = KeyModifiers::empty();
for token in tokens {
let flag = match token {
"S" => KeyModifiers::SHIFT,
"A" => KeyModifiers::ALT,
"C" => KeyModifiers::CONTROL,
"Meta" | "Cmd" | "Win" => KeyModifiers::SUPER,
_ => return Err(anyhow!("Invalid key modifier '{}-'", token)),
};
if modifiers.contains(flag) {
return Err(anyhow!("Repeated key modifier '{}-'", token));
}
modifiers.insert(flag);
}
// Normalize character keys so that characters like C-S-r and C-R
// are represented by equal KeyEvents.
match code {
KeyCode::Char(ch)
if ch.is_ascii_lowercase() && modifiers.contains(KeyModifiers::SHIFT) =>
{
code = KeyCode::Char(ch.to_ascii_uppercase());
modifiers.remove(KeyModifiers::SHIFT);
}
_ => (),View on GitHub (pinned to 079a789e8c)
Solutions
- Use the single letters: C for control, S for shift, A for alt; use Meta, Cmd, or Win for the super key.
- Order does not matter but spelling does: "C-a" not "Ctrl-a".
- Modifier names are case-sensitive; lowercase "c-a" is invalid.
Example fix
# before (config.toml) "Ctrl-s" = "write" # after "C-s" = "write"
Defensive patterns
Strategy: validation
Validate before calling
const MODIFIERS: &[&str] = &["S", "A", "C", "Meta", "Cmd", "Win"];
fn modifiers_valid(spec: &str) -> bool {
spec.split('-')
.filter(|t| !t.is_empty())
.take_while(|t| *t != spec.rsplit('-').next().unwrap_or(""))
.all(|t| MODIFIERS.contains(&t))
} Type guard
fn parse_modifier(tok: &str) -> Option<crossterm::event::KeyModifiers> {
match tok {
"S" => Some(KeyModifiers::SHIFT),
"A" => Some(KeyModifiers::ALT),
"C" => Some(KeyModifiers::CONTROL),
"Meta" | "Cmd" | "Win" => Some(KeyModifiers::SUPER),
_ => None,
}
} Try / catch
let ev = match spec.parse::<KeyEvent>() {
Ok(ev) => ev,
Err(err) if err.to_string().contains("Invalid key modifier") => {
return Err(anyhow!("'{spec}': use C/S/A or Meta/Cmd/Win as modifiers"));
}
Err(err) => return Err(err),
}; Prevention
- Translate ctrl/shift/alt long forms to C/S/A when porting keymaps.
- Modifier tokens are case-sensitive; uppercase only (except Meta/Cmd/Win).
When it happens
Trigger: Keymap entries like "Ctrl-a", "Shift-b", "Alt-x", "ctrl-c" (case matters), or "M-x" (M is not recognized; super is Meta/Cmd/Win).
Common situations: Porting keymaps from VS Code (ctrl+...) or Emacs (M-, C- prefix styles); assuming case-insensitivity; using "Cmd" on one platform and "Win" spellings elsewhere — both fine — but "Super" is not.
Related errors
- Repeated key modifier '{}-'
- Missing key code
- Invalid function key '{}'
- Key '-' cannot be used with modifiers, use '{}' instead
- Invalid key code '{}'
AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16).
Data as JSON: /api/errors/e49202505055749c.
Report an issue: GitHub.