tui-cs/Terminal.Gui · error · JsonException

Configuration JSON root must not be null.

Error message

Configuration JSON root must not be null.

What it means

Thrown by SourcesManager.Load(Stream,...) when JsonSerializer.Deserialize returns null for the SettingsScope root — meaning the JSON document's root token was the literal 'null'. Terminal.Gui requires a JSON object as the configuration root. Note: this JsonException is caught immediately after (SourcesManager.cs:177) and only re-thrown if ConfigurationManager.ThrowOnJsonErrors is true (default false); otherwise it is recorded via ConfigurationManager.AddJsonError and printed at Application shutdown.

Source

Thrown at Terminal.Gui/Configuration/SourcesManager.cs:163

    {
        if (settingsScope is null)
        {
            return false;
        }

        // Update the existing settings with the new settings.
        try
        {
#if DEBUG
            string? json = new StreamReader (stream).ReadToEnd ();
            stream.Position = 0;
            Debug.Assert (json != null);
#endif
            SettingsScope? scope = JsonSerializer.Deserialize (stream, TuiSerializerContext.Instance.SettingsScope);

            if (scope is null)
            {
                throw new JsonException ("Configuration JSON root must not be null.");
            }

            settingsScope.UpdateFrom (scope);
            ConfigurationManager.OnUpdated ();

            AddSource (location, source);

            Logging.Trace ($"Read configuration from \"{source}\" - ConfigLocation: {location}");

            Trace.Configuration (source, "Load", $"location={location}");

            return true;
        }
        catch (JsonException e)
        {
            if (ConfigurationManager.ThrowOnJsonErrors ?? false)
            {
                throw;

View on GitHub (pinned to 2e47b11478)

Solutions

  1. Replace the file contents with a valid JSON object (at minimum '{}') or delete the file so Terminal.Gui falls back to defaults.
  2. Set ConfigurationManager.ThrowOnJsonErrors = false (the default) so a bad file is logged but does not crash startup, then fix the file.
  3. If it comes from TUI_CONFIG, unset the env var or point it at a valid JSON object.

Example fix

// before: .tui/config.json
null
// after: .tui/config.json
{
  "Theme": "Default"
}
Defensive patterns

Strategy: validation

Validate before calling

// Reject a 'null' root before handing the stream to Terminal.Gui
using JsonDocument doc = JsonDocument.Parse (stream);
stream.Position = 0;
if (doc.RootElement.ValueKind == JsonValueKind.Null)
    throw new InvalidOperationException ("Config root is the literal null; replace with an object.");

Type guard

static bool IsConfigRootValid (Stream s)
{ s.Position = 0; try { using var d = JsonDocument.Parse (s); return d.RootElement.ValueKind == JsonValueKind.Object; } catch { return false; } finally { s.Position = 0; } }

Try / catch

ConfigurationManager.ThrowOnJsonErrors = false; // default; logs instead of throwing
try { /* load */ } catch (JsonException ex) when (ex.Message.Contains ("must not be null")) { /* handle */ }

Prevention

When it happens

Trigger: A config file (.tui/config.json, <App>.config.json, a TUI_CONFIG-pointed file, or an embedded resource) whose entire contents are the four bytes 'null'. Also possible if a custom RuntimeConfig string is set to "null".

Common situations: A tool or script wrote the literal string "null" into the config file; a previous failed write left a placeholder; a user typed 'null' thinking it clears settings.

Related errors


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