helix-editor/helix · error · anyhow::Error
Key '-' cannot be used with modifiers, use '{}' instead
Error message
Key '-' cannot be used with modifiers, use '{}' instead What it means
The '-' character is ambiguous because '-' is the modifier separator in key specs, so a bare trailing '-' code combined with modifiers ("C--") cannot be represented that way. FromStr detects a spec ending in '-' with an empty final token and, unless the whole spec is just "-", rejects it and suggests the special key name: "{modifiers}-minus".
Source
Thrown at helix-view/src/input.rs:410
function if function.len() > 1 && function.starts_with('F') => {
let function: String = function.chars().skip(1).collect();
let function = str::parse::<u8>(&function)?;
(function > 0 && function < 25)
.then_some(KeyCode::F(function))
.ok_or_else(|| anyhow!("Invalid function key '{}'", function))?
}
// Checking that the last token is empty ensures that this branch is only taken if
// `-` is used as a code. For example this branch will not be taken for `S-` (which is
// missing a code).
_ if s.ends_with('-') && tokens.last().is_some_and(|t| t.is_empty()) => {
if s == "-" {
return Ok(KeyEvent {
code: KeyCode::Char('-'),
modifiers: KeyModifiers::empty(),
});
} 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)),
};
View on GitHub (pinned to 079a789e8c)
Solutions
- Replace the trailing '-' with the special key name: "C--" becomes "C-minus", "A--" becomes "A-minus".
- A plain '-' with no modifiers is fine as-is and needs no change.
- The error message itself prints the exact suggested binding — use it.
Example fix
# before (config.toml) "C--" = "decrease_font_size" # after "C-minus" = "decrease_font_size"
Defensive patterns
Strategy: validation
Validate before calling
fn normalize_minus(spec: &str) -> String {
if spec.len() > 1 && spec.ends_with('-') {
format!("{}minus", spec)
} else {
spec.to_string()
}
}
let ev = normalize_minus(spec).parse::<KeyEvent>()?; Try / catch
if let Err(err) = spec.parse::<KeyEvent>() {
let msg = err.to_string();
if msg.contains("cannot be used with modifiers") {
// message already contains the corrected binding, e.g. "use 'C-minus' instead"
return Err(anyhow!("{msg} (from spec '{spec}')"));
}
return Err(err);
} Prevention
- Always spell modifier+minus as "{MOD}-minus".
- Run a config lint pass that rewrites trailing '-' codes to minus.
- Note plain '-' alone is valid; only combined forms are rejected.
When it happens
Trigger: Keymap entries like "C--" or "A--" intending Ctrl+minus / Alt+minus; writing "S--" for shift-minus.
Common situations: Binding font-zoom-out or decrement actions to Ctrl/Alt+Minus; configs ported from formats that accept "C--" (Kakoune style) without translation.
Related errors
- Missing key code
- Invalid function key '{}'
- Invalid key code '{}'
- Invalid key modifier '{}-'
- Repeated key modifier '{}-'
AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16).
Data as JSON: /api/errors/b72875bb95d04906.
Report an issue: GitHub.