tui-cs/Terminal.Gui · error · JsonException

After {propertyName}: Expected Attribute but got {attrObj?.G

Error message

After {propertyName}: Expected Attribute but got {attrObj?.GetType ().Name ?? "null"} when parsing Scheme.

What it means

A Scheme property's value was read by the Attribute deserializer (TuiSerializerContext.Attribute), but the result is not an Attribute — typically because the value was JSON null or structurally wrong for an Attribute, so the converter returned null or a different type.

Source

Thrown at Terminal.Gui/Configuration/SchemeJsonConverter.cs:41

            if (reader.TokenType == JsonTokenType.EndObject)
            {
                return scheme;
            }

            if (reader.TokenType != JsonTokenType.PropertyName)
            {
                throw new JsonException ($"After {propertyName}: Expected PropertyName but got another token when parsing Attribute: {reader.TokenType}.");
            }

            propertyName = reader.GetString ();
            reader.Read ();

            // Make sure attributes are marked as explicitly set when deserialized
            object? attrObj = JsonSerializer.Deserialize (ref reader, TuiSerializerContext.Instance.Attribute);

            if (attrObj is not Attribute attribute)
            {
                throw new JsonException ($"After {propertyName}: Expected Attribute but got {attrObj?.GetType ().Name ?? "null"} when parsing Scheme.");
            }
            if (propertyName is { })
            {
                scheme = propertyName.ToLowerInvariant () switch
                {
                    "normal" => scheme with { Normal = attribute },
                    "hotnormal" => scheme with { HotNormal = attribute },
                    "focus" => scheme with { Focus = attribute },
                    "hotfocus" => scheme with { HotFocus = attribute },
                    "active" => scheme with { Active = attribute },
                    "hotactive" => scheme with { HotActive = attribute },
                    "highlight" => scheme with { Highlight = attribute },
                    "editable" => scheme with { Editable = attribute },
                    "readonly" => scheme with { ReadOnly = attribute },
                    "disabled" => scheme with { Disabled = attribute },
                    "code" => scheme with { Code = attribute },
                    "codecomment" => scheme with { CodeComment = attribute },
                    "codekeyword" => scheme with { CodeKeyword = attribute },

View on GitHub (pinned to 2e47b11478)

Solutions

  1. Provide a complete Attribute object with Foreground/Background (e.g. { "Foreground": "White", "Background": "Blue" }).
  2. Remove the role entry entirely instead of setting it to null — the Scheme falls back to defaults.

Example fix

// before
"Normal": null
// after
"Normal": { "Foreground": "White", "Background": "Blue" }
Defensive patterns

Strategy: validation

Validate before calling

using var doc = JsonDocument.Parse (configText);
// For each Scheme role, assert the value is a non-null object with color fields
foreach (JsonProperty role in schemeEl.EnumerateObject ())
{
    if (role.Value.ValueKind != JsonValueKind.Object) return false;
}

Try / catch

try { ConfigurationManager.Apply (); }
catch (JsonException ex) when (ex.Message.Contains ("Expected Attribute"))
{ /* ex.Message names the role that failed */ }

Prevention

When it happens

Trigger: "Normal": null where an Attribute is required, or a value shape the AttributeJsonConverter cannot map (e.g. a bare string that is not a valid color).

Common situations: Setting a role to null in JSON; providing a malformed Attribute object missing required color fields.

Related errors


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