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

  1. Replace the trailing '-' with the special key name: "C--" becomes "C-minus", "A--" becomes "A-minus".
  2. A plain '-' with no modifiers is fine as-is and needs no change.
  3. 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

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


AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16). Data as JSON: /api/errors/b72875bb95d04906. Report an issue: GitHub.