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
- Provide a complete Attribute object with Foreground/Background (e.g. { "Foreground": "White", "Background": "Blue" }).
- 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
- Never set a VisualRole to null in theme JSON.
- Omit a role rather than null it; the Scheme falls back to defaults.
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
- Unexpected StartObject token when parsing Scheme: {reader.To
- {propertyName}: Unrecognized Scheme Attribute name.
- {propertyName}: Unexpected token when parsing Attribute: {re
- {propertyName}: Expected a string value.
- Expected a valid text style value.
AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13).
Data as JSON: /api/errors/e93ad7705b5daf13.
Report an issue: GitHub.