tui-cs/Terminal.Gui · error · JsonException
Expected a JSON object ("{ "propName" : ... }"), but got "{r
Error message
Expected a JSON object ("{ "propName" : ... }"), but got "{reader.TokenType}". What it means
ScopeJsonConverter.Read (used for SettingsScope and ThemeScope) expects a JSON object at the current position. If the token is not StartObject (e.g. an array, string, number, or true/false where a scope object is expected), it throws.
Source
Thrown at Terminal.Gui/Configuration/ScopeJsonConverter.cs:35
/// <typeparam name="TScopeT"></typeparam>
internal class ScopeJsonConverter<
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor
| DynamicallyAccessedMemberTypes.PublicProperties)]
TScopeT> : JsonConverter<TScopeT> where TScopeT : Scope<TScopeT>
{
[UnconditionalSuppressMessage ("AOT",
"IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.",
Justification =
"Arbitrary property-level converter fallback is guarded by RuntimeFeature.IsDynamicCodeSupported and is unreachable under NativeAOT.")]
[UnconditionalSuppressMessage ("Trimming",
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
Justification =
"Arbitrary property-level converter fallback is only used when a consumer opts into a custom property-level JsonConverter on JIT-supported runtimes.")]
public override TScopeT Read (ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
{
throw new JsonException ($$"""Expected a JSON object ("{ "propName" : ... }"), but got "{{reader.TokenType}}".""");
}
var scope = (TScopeT)Activator.CreateInstance (typeof (TScopeT))!;
var propertyName = string.Empty;
while (reader.Read ())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
return scope!;
}
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException ($"After {propertyName}: Expected a JSON property name, but got \"{reader.TokenType}\"");
}
propertyName = reader.GetString ();View on GitHub (pinned to 2e47b11478)
Solutions
- Ensure the config root and each theme entry are JSON objects.
- Validate the document structure against the expected schema.
Example fix
// before
[ { "Theme": { ... } } ]
// after
{ "Themes": [ { ... } ] } Defensive patterns
Strategy: validation
Validate before calling
using var doc = JsonDocument.Parse (configText); if (doc.RootElement.ValueKind != JsonValueKind.Object) return false;
Try / catch
try { ConfigurationManager.Apply (); }
catch (JsonException ex) when (ex.Message.Contains ("Expected a JSON object"))
{ /* the token type in ex.Message shows what was found instead */ } Prevention
- Validate the top-level JSON is an object before loading.
- Diff against the default config layout.
When it happens
Trigger: The top-level config or a theme entry is mapped to a non-object, e.g. the whole config file is a JSON array, or a theme value is a bare string instead of an object.
Common situations: Malformed config file structure; wrong root element; tooling emitting arrays where objects are expected.
Related errors
- After {propertyName}: Expected a JSON property name, but got
- After {propertyName}: Expected PropertyName but got another
- After {propertyName}: Invalid Json.
- {propertyName}: Unknown property name.
- Unexpected StartObject token when parsing Attribute: {reader
AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13).
Data as JSON: /api/errors/4f2ddaaf372a55d5.
Report an issue: GitHub.