tui-cs/Terminal.Gui · error · ArgumentException

HotKey must be a printable key ({hotKey}).

Error message

HotKey must be a printable key ({hotKey}).

What it means

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.

Source

Thrown at Terminal.Gui/ViewBase/View.Keyboard.cs:138

    /// <param name="prevHotKey">The HotKey <paramref name="hotKey"/> is replacing. Key bindings for this key will be removed.</param>
    /// <param name="hotKey">The new HotKey. If <see cref="Key.Empty"/> <paramref name="prevHotKey"/> bindings will be removed.</param>
    /// <param name="data">Arbitrary data that can be associated with this key binding.</param>
    /// <returns><see langword="true"/> if the HotKey bindings were added.</returns>
    /// <exception cref="ArgumentException"></exception>
    public bool AddKeyBindingsForHotKey (Key prevHotKey, Key hotKey, object? data = null)
    {
        if (_hotKey == hotKey)
        {
            return false;
        }

        Key newKey = hotKey;

        Key baseKey = newKey.NoAlt.NoShift.NoCtrl;

        if (newKey != Key.Empty && Rune.IsControl (baseKey.AsRune))
        {
            throw new ArgumentException (@$"HotKey must be a printable key ({hotKey}).");
        }

        if (newKey != baseKey)
        {
            if (newKey.IsCtrl)
            {
                throw new ArgumentException (@$"HotKey does not support CtrlMask ({hotKey}).");
            }

            // Strip off the shift mask if it's A...Z
            if (baseKey.IsKeyCodeAtoZ)
            {
                newKey = newKey.NoShift;
            }

            // Strip off the Alt mask
            newKey = newKey.NoAlt;
        }

View on GitHub (pinned to 2e47b11478)

Solutions

  1. Use a letter (Key.A–Key.Z) or digit (Key.D0–Key.D9) as the hot key.
  2. If you need a non-printable key binding, use KeyBindings.Add instead of HotKey.
  3. Filter out control keys before assignment if reading from user input.

Example fix

// before
view.HotKey = Key.Enter;
// after
view.KeyBindings.Add (Key.Enter, Command.Accept);
Defensive patterns

Strategy: validation

Validate before calling

Key baseKey = candidate.NoAlt.NoShift.NoCtrl;
if (candidate != Key.Empty && Rune.IsControl (baseKey.AsRune))
    throw new ArgumentException ($"HotKey must be printable: {candidate}");
view.HotKey = candidate;

Type guard

static bool IsPrintableHotKey (Key k) => k == Key.Empty || !Rune.IsControl (k.NoAlt.NoShift.NoCtrl.AsRune);

Prevention

When it happens

Trigger: Setting view.HotKey = Key.Tab, Key.Enter, Key.Esc, Key.F1, or any key whose base rune is a control character.

Common situations: 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.

Related errors


AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13). Data as JSON: /api/errors/c20d02d940d0e5da. Report an issue: GitHub.