{"record":{"id":"7f4133fc13e6f832","repo":"tui-cs/Terminal.Gui","slug":"expected-a-json-array-but-got","errorCode":null,"errorMessage":"Expected a JSON array (\"[ {{ ... }} ]\"), but got \"{reader.TokenType}\".","messagePattern":"Expected a JSON array \\(\"\\[ (.+?)\\} \\]\"\\), but got \"(.+?)\"\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/Configuration/ConcurrentDictionaryJsonConverter.cs","lineNumber":18,"sourceCode":"#nullable disable\nusing System.Collections.Concurrent;\nusing System.Text.Json;\nusing System.Text.Json.Serialization;\n\nnamespace Terminal.Gui.Configuration;\n\ninternal class ConcurrentDictionaryJsonConverter<T> : JsonConverter<ConcurrentDictionary<string, T>>\n{\n    public override ConcurrentDictionary<string, T> Read (\n        ref Utf8JsonReader reader,\n        Type typeToConvert,\n        JsonSerializerOptions options\n    )\n    {\n        if (reader.TokenType != JsonTokenType.StartArray)\n        {\n            throw new JsonException ($\"Expected a JSON array (\\\"[ {{ ... }} ]\\\"), but got \\\"{reader.TokenType}\\\".\");\n        }\n\n        // If the Json options indicate ignoring case, use the invariant culture ignore case comparer\n        ConcurrentDictionary<string, T> dictionary = new (\n                                                          options.PropertyNameCaseInsensitive\n                                                              ? StringComparer.InvariantCultureIgnoreCase\n                                                              : StringComparer.InvariantCulture);\n\n        while (reader.Read ())\n        {\n            if (reader.TokenType == JsonTokenType.StartObject)\n            {\n                reader.Read ();\n\n                if (reader.TokenType == JsonTokenType.PropertyName)\n                {\n                    string key = reader.GetString ();\n                    reader.Read ();","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/Configuration/ConcurrentDictionaryJsonConverter.cs#L1-L36","documentation":"Thrown by ConcurrentDictionaryJsonConverter<T>.Read: Terminal.Gui serializes its ConcurrentDictionary<string,T> properties (e.g. Themes) as a JSON ARRAY of single-key objects ([ {\"key\": value}, ... ]), not as a JSON object. If the reader's first token is not StartArray, this fires.","triggerScenarios":"A config file provides Themes as a JSON object { \"Default\": {...} } instead of an array [ {\"Default\": {...}} ]. Also fires on a bare scalar or string where the array is expected.","commonSituations":"Author assumes the natural JSON object shape for a map; migrating from a system that uses object-form maps; hand-editing a Themes section.","solutions":["Wrap each key/value pair as its own object inside an array: [ {\"ThemeName\": { ...scheme... } } ].","Export a config from ConfigurationManager once to see the exact array shape it expects, then mirror it.","Use a JSON schema for the config to enforce the array shape."],"exampleFix":"// before\n\"Themes\": { \"Default\": { ... } }\n// after\n\"Themes\": [ { \"Default\": { ... } } ]","handlingStrategy":"validation","validationCode":"// Themes must be a JSON array of single-key objects.\nusing var doc = JsonDocument.Parse (jsonString);\nif (doc.RootElement.GetProperty (\"Themes\").ValueKind != JsonValueKind.Array)\n    throw new FormatException (\"Themes must be a JSON array [ {key: value}, ... ].\");","typeGuard":"static bool ThemesIsArrayShape (JsonElement themes) =>\n    themes.ValueKind == JsonValueKind.Array\n    && themes.EnumerateArray ().All (e => e.ValueKind == JsonValueKind.Object && e.EnumerateObject ().Count () == 1);","tryCatchPattern":"try { ConfigurationManager.Load (locations); }\ncatch (JsonException ex) when (ex.Message.Contains (\"Expected a JSON array\"))\n{ /* rewrap the object-form Themes into an array */ }","preventionTips":["Serialize a sample config once to capture the array shape for Themes.","Add a JSON schema that types Themes as array-of-single-key-objects."],"tags":["configuration","json","theming","dictionary","themes"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}