{"record":{"id":"e49202505055749c","repo":"helix-editor/helix","slug":"invalid-key-modifier","errorCode":null,"errorMessage":"Invalid key modifier '{}-'","messagePattern":"Invalid key modifier '(.+?)-'","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"helix-view/src/input.rs","lineNumber":426,"sourceCode":"                } else {\n                    let suggestion = format!(\"{}-{}\", s.trim_end_matches('-'), keys::MINUS);\n                    return Err(anyhow!(\n                        \"Key '-' cannot be used with modifiers, use '{}' instead\",\n                        suggestion\n                    ));\n                }\n            }\n            invalid => return Err(anyhow!(\"Invalid key code '{}'\", invalid)),\n        };\n\n        let mut modifiers = KeyModifiers::empty();\n        for token in tokens {\n            let flag = match token {\n                \"S\" => KeyModifiers::SHIFT,\n                \"A\" => KeyModifiers::ALT,\n                \"C\" => KeyModifiers::CONTROL,\n                \"Meta\" | \"Cmd\" | \"Win\" => KeyModifiers::SUPER,\n                _ => return Err(anyhow!(\"Invalid key modifier '{}-'\", token)),\n            };\n\n            if modifiers.contains(flag) {\n                return Err(anyhow!(\"Repeated key modifier '{}-'\", token));\n            }\n            modifiers.insert(flag);\n        }\n\n        // Normalize character keys so that characters like C-S-r and C-R\n        // are represented by equal KeyEvents.\n        match code {\n            KeyCode::Char(ch)\n                if ch.is_ascii_lowercase() && modifiers.contains(KeyModifiers::SHIFT) =>\n            {\n                code = KeyCode::Char(ch.to_ascii_uppercase());\n                modifiers.remove(KeyModifiers::SHIFT);\n            }\n            _ => (),","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/helix-editor/helix/blob/079a789e8cb08ead67f19e1971a1b7438b37354b/helix-view/src/input.rs#L408-L444","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"# before (config.toml)\n \"Ctrl-s\" = \"write\"\n\n# after\n \"C-s\" = \"write\"","handlingStrategy":"validation","validationCode":"const MODIFIERS: &[&str] = &[\"S\", \"A\", \"C\", \"Meta\", \"Cmd\", \"Win\"];\n\nfn modifiers_valid(spec: &str) -> bool {\n    spec.split('-')\n        .filter(|t| !t.is_empty())\n        .take_while(|t| *t != spec.rsplit('-').next().unwrap_or(\"\"))\n        .all(|t| MODIFIERS.contains(&t))\n}","typeGuard":"fn parse_modifier(tok: &str) -> Option<crossterm::event::KeyModifiers> {\n    match tok {\n        \"S\" => Some(KeyModifiers::SHIFT),\n        \"A\" => Some(KeyModifiers::ALT),\n        \"C\" => Some(KeyModifiers::CONTROL),\n        \"Meta\" | \"Cmd\" | \"Win\" => Some(KeyModifiers::SUPER),\n        _ => None,\n    }\n}","tryCatchPattern":"let ev = match spec.parse::<KeyEvent>() {\n    Ok(ev) => ev,\n    Err(err) if err.to_string().contains(\"Invalid key modifier\") => {\n        return Err(anyhow!(\"'{spec}': use C/S/A or Meta/Cmd/Win as modifiers\"));\n    }\n    Err(err) => return Err(err),\n};","preventionTips":["Translate ctrl/shift/alt long forms to C/S/A when porting keymaps.","Modifier tokens are case-sensitive; uppercase only (except Meta/Cmd/Win)."],"tags":["keymap","input","modifiers","helix","rust"],"backgroundTag":null,"analyzedSha":"079a789e8cb08ead67f19e1971a1b7438b37354b","analyzedAt":"2026-08-16T09:09:59.668Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}