{"record":{"id":"4f2ddaaf372a55d5","repo":"tui-cs/Terminal.Gui","slug":"expected-a-json-object-propname-b","errorCode":null,"errorMessage":"Expected a JSON object (\"{ \"propName\" : ... }\"), but got \"{reader.TokenType}\".","messagePattern":"Expected a JSON object \\(\"(.+?)\"\\), but got \"(.+?)\"\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/Configuration/ScopeJsonConverter.cs","lineNumber":35,"sourceCode":"/// <typeparam name=\"TScopeT\"></typeparam>\ninternal class ScopeJsonConverter<\n    [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor\n                                 | DynamicallyAccessedMemberTypes.PublicProperties)]\nTScopeT> : JsonConverter<TScopeT> where TScopeT : Scope<TScopeT>\n{\n    [UnconditionalSuppressMessage (\"AOT\",\n                                   \"IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.\",\n                                   Justification =\n                                       \"Arbitrary property-level converter fallback is guarded by RuntimeFeature.IsDynamicCodeSupported and is unreachable under NativeAOT.\")]\n    [UnconditionalSuppressMessage (\"Trimming\",\n                                   \"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code\",\n                                   Justification =\n                                       \"Arbitrary property-level converter fallback is only used when a consumer opts into a custom property-level JsonConverter on JIT-supported runtimes.\")]\n    public override TScopeT Read (ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n    {\n        if (reader.TokenType != JsonTokenType.StartObject)\n        {\n            throw new JsonException ($$\"\"\"Expected a JSON object (\"{ \"propName\" : ... }\"), but got \"{{reader.TokenType}}\".\"\"\");\n        }\n\n        var scope = (TScopeT)Activator.CreateInstance (typeof (TScopeT))!;\n        var propertyName = string.Empty;\n\n        while (reader.Read ())\n        {\n            if (reader.TokenType == JsonTokenType.EndObject)\n            {\n                return scope!;\n            }\n\n            if (reader.TokenType != JsonTokenType.PropertyName)\n            {\n                throw new JsonException ($\"After {propertyName}: Expected a JSON property name, but got \\\"{reader.TokenType}\\\"\");\n            }\n\n            propertyName = reader.GetString ();","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/Configuration/ScopeJsonConverter.cs#L17-L53","documentation":"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.","triggerScenarios":"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.","commonSituations":"Malformed config file structure; wrong root element; tooling emitting arrays where objects are expected.","solutions":["Ensure the config root and each theme entry are JSON objects.","Validate the document structure against the expected schema."],"exampleFix":"// before\n[ { \"Theme\": { ... } } ]\n// after\n{ \"Themes\": [ { ... } ] }","handlingStrategy":"validation","validationCode":"using var doc = JsonDocument.Parse (configText);\nif (doc.RootElement.ValueKind != JsonValueKind.Object) return false;","typeGuard":null,"tryCatchPattern":"try { ConfigurationManager.Apply (); }\ncatch (JsonException ex) when (ex.Message.Contains (\"Expected a JSON object\"))\n{ /* the token type in ex.Message shows what was found instead */ }","preventionTips":["Validate the top-level JSON is an object before loading.","Diff against the default config layout."],"tags":["config","json","scope","syntax"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}