tui-cs/Terminal.Gui · error · InvalidOperationException

DefaultKeyBindings dictionary is null. Initialize it before

Error message

DefaultKeyBindings dictionary is null. Initialize it before setting individual bindings.

What it means

Thrown by Application.SetDefaultKeyBinding when the static DefaultKeyBindings dictionary is null. The dictionary is field-initialized with sensible defaults (Quit, Suspend, NextTabStop, etc.), so it is only null if application code or a ConfigurationManager JSON theme explicitly assigned null to Application.DefaultKeyBindings. The guard exists because SetDefaultKeyBinding indexes directly into the dictionary and a null dereference would otherwise produce a less helpful NullReferenceException.

Source

Thrown at Terminal.Gui/App/Application.cs:344

    /// <summary>
    ///     Raised when the <see cref="DefaultKeyBindings"/> are changed — either by replacing the entire dictionary
    ///     (property setter) or by calling <see cref="SetDefaultKeyBinding"/> / <see cref="RemoveDefaultKeyBinding"/>.
    /// </summary>
    public static event EventHandler? DefaultKeyBindingsChanged;

    /// <summary>
    ///     Sets (or replaces) the key binding for a single <paramref name="command"/> in <see cref="DefaultKeyBindings"/>
    ///     and raises <see cref="DefaultKeyBindingsChanged"/> so that subscribers (e.g. <c>ApplicationKeyboard</c>)
    ///     pick up the change immediately.
    /// </summary>
    /// <param name="command">The command whose binding should be set.</param>
    /// <param name="binding">The platform key binding to associate with <paramref name="command"/>.</param>
    public static void SetDefaultKeyBinding (Command command, PlatformKeyBinding binding)
    {
        if (DefaultKeyBindings is null)
        {
            throw new InvalidOperationException ("DefaultKeyBindings dictionary is null. Initialize it before setting individual bindings.");
        }

        DefaultKeyBindings [command] = binding;
        Trace.Configuration ("DefaultKeyBindings", "SetDefaultKeyBinding", $"{command}=[{binding}]");
        DefaultKeyBindingsChanged?.Invoke (null, EventArgs.Empty);
    }

    /// <summary>
    ///     Removes the key binding for <paramref name="command"/> from <see cref="DefaultKeyBindings"/>
    ///     and raises <see cref="DefaultKeyBindingsChanged"/> so that subscribers pick up the change immediately.
    /// </summary>
    /// <param name="command">The command whose binding should be removed.</param>
    /// <returns><see langword="true"/> if the binding was found and removed; otherwise <see langword="false"/>.</returns>
    public static bool RemoveDefaultKeyBinding (Command command)
    {
        if (DefaultKeyBindings is null || !DefaultKeyBindings.Remove (command))
        {
            return false;

View on GitHub (pinned to 2e47b11478)

Solutions

  1. Before calling SetDefaultKeyBinding, ensure Application.DefaultKeyBindings is non-null: if (Application.DefaultKeyBindings is null) Application.DefaultKeyBindings = new ();
  2. Audit any code or config that assigns Application.DefaultKeyBindings (search for 'DefaultKeyBindings =' and ConfigurationManager.Apply calls) and ensure it never assigns null.
  3. If a config JSON is responsible, validate the DefaultKeyBindings section is either omitted (to keep defaults) or a valid object, never null.
  4. In test teardown, restore the field initializer instead of nullifying: reassign the default dictionary literal or call the reset routine that re-establishes defaults.

Example fix

// before
Application.DefaultKeyBindings = null;
Application.SetDefaultKeyBinding (Command.Quit, Bind.All (Key.Q.WithCtrl));

// after
Application.DefaultKeyBindings ??= new ();
Application.SetDefaultKeyBinding (Command.Quit, Bind.All (Key.Q.WithCtrl));
Defensive patterns

Strategy: validation

Validate before calling

if (Application.DefaultKeyBindings is null)
{
    Application.DefaultKeyBindings = new Dictionary<Command, PlatformKeyBinding> ();
}
Application.SetDefaultKeyBinding (Command.Quit, Bind.All (Key.Q.WithCtrl));

Type guard

static bool HasDefaultKeyBindings () => Application.DefaultKeyBindings is not null;

Prevention

When it happens

Trigger: Calling Application.SetDefaultKeyBinding(command, binding) after code somewhere set Application.DefaultKeyBindings = null. Common culprits: a config/theme JSON file that serialized the dictionary as null and applied it via ConfigurationManager, or a reset/cleanup routine that nullified the property, or test teardown that set it to null without restoring it.

Common situations: Loading a custom Terminal.Gui config JSON whose DefaultKeyBindings section is malformed or explicitly null; running unit tests that mutate DefaultKeyBindings and fail to restore the initialized dictionary in teardown; programmatic theme switching code that sets the whole dictionary and hits a null branch.

Related errors


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