{"record":{"id":"c20d02d940d0e5da","repo":"tui-cs/Terminal.Gui","slug":"hotkey-must-be-a-printable-key-hotkey","errorCode":null,"errorMessage":"HotKey must be a printable key ({hotKey}).","messagePattern":"HotKey must be a printable key \\((.+?)\\)\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/ViewBase/View.Keyboard.cs","lineNumber":138,"sourceCode":"    /// <param name=\"prevHotKey\">The HotKey <paramref name=\"hotKey\"/> is replacing. Key bindings for this key will be removed.</param>\n    /// <param name=\"hotKey\">The new HotKey. If <see cref=\"Key.Empty\"/> <paramref name=\"prevHotKey\"/> bindings will be removed.</param>\n    /// <param name=\"data\">Arbitrary data that can be associated with this key binding.</param>\n    /// <returns><see langword=\"true\"/> if the HotKey bindings were added.</returns>\n    /// <exception cref=\"ArgumentException\"></exception>\n    public bool AddKeyBindingsForHotKey (Key prevHotKey, Key hotKey, object? data = null)\n    {\n        if (_hotKey == hotKey)\n        {\n            return false;\n        }\n\n        Key newKey = hotKey;\n\n        Key baseKey = newKey.NoAlt.NoShift.NoCtrl;\n\n        if (newKey != Key.Empty && Rune.IsControl (baseKey.AsRune))\n        {\n            throw new ArgumentException (@$\"HotKey must be a printable key ({hotKey}).\");\n        }\n\n        if (newKey != baseKey)\n        {\n            if (newKey.IsCtrl)\n            {\n                throw new ArgumentException (@$\"HotKey does not support CtrlMask ({hotKey}).\");\n            }\n\n            // Strip off the shift mask if it's A...Z\n            if (baseKey.IsKeyCodeAtoZ)\n            {\n                newKey = newKey.NoShift;\n            }\n\n            // Strip off the Alt mask\n            newKey = newKey.NoAlt;\n        }","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/ViewBase/View.Keyboard.cs#L120-L156","documentation":"A HotKey must be a printable character. The base key (with Alt/Shift/Ctrl stripped) is checked against Rune.IsControl — control characters like Tab, Enter, Esc, or function keys cannot serve as hot keys because they are not displayable glyphs the user can see highlighted in a title.","triggerScenarios":"Setting view.HotKey = Key.Tab, Key.Enter, Key.Esc, Key.F1, or any key whose base rune is a control character.","commonSituations":"Assigning a key code from a KeyPressed event directly as a HotKey without filtering; trying to use an arrow or function key as a mnemonic.","solutions":["Use a letter (Key.A–Key.Z) or digit (Key.D0–Key.D9) as the hot key.","If you need a non-printable key binding, use KeyBindings.Add instead of HotKey.","Filter out control keys before assignment if reading from user input."],"exampleFix":"// before\nview.HotKey = Key.Enter;\n// after\nview.KeyBindings.Add (Key.Enter, Command.Accept);","handlingStrategy":"validation","validationCode":"Key baseKey = candidate.NoAlt.NoShift.NoCtrl;\nif (candidate != Key.Empty && Rune.IsControl (baseKey.AsRune))\n    throw new ArgumentException ($\"HotKey must be printable: {candidate}\");\nview.HotKey = candidate;","typeGuard":"static bool IsPrintableHotKey (Key k) => k == Key.Empty || !Rune.IsControl (k.NoAlt.NoShift.NoCtrl.AsRune);","tryCatchPattern":null,"preventionTips":["Use letters or digits for hot keys.","Use KeyBindings.Add for non-printable shortcuts.","Filter user-input keys before assignment."],"tags":["hotkey","keyboard","validation"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}