{"record":{"id":"fdee1e3fe55eedf9","repo":"BCUninstaller/Bulk-Crap-Uninstaller","slug":"expected-string-or-array-token-but-got-reader-tok","errorCode":null,"errorMessage":"Expected string or array token but got {reader.TokenType}","messagePattern":"Expected string or array token but got (.+?)","errorType":"validation","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"source/UninstallTools/Factory/Json/DynamicStringArrayConverter.cs","lineNumber":26,"sourceCode":"    /// <summary>\n    /// Handle JSON string array entry that has one dimension less or more.\n    /// </summary>\n    internal class DynamicStringArrayConverter : JsonConverter<string[]>\n    {\n        public override string[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)\n        {\n            // 0-dimension\n            if (reader.TokenType == JsonTokenType.String)\n                return new[] { reader.GetString() };\n\n            if (reader.TokenType == JsonTokenType.StartArray)\n            {\n                var results = new List<string>();\n                ReadStrings(ref reader, results);\n                return results.ToArray();\n            }\n\n            throw new JsonException($\"Expected string or array token but got {reader.TokenType}\");\n        }\n\n        private static void ReadStrings(ref Utf8JsonReader reader, List<string> results)\n        {\n            while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)\n            {\n                switch (reader.TokenType)\n                {\n                    // normal\n                    case JsonTokenType.String:\n                        results.Add(reader.GetString());\n                        break;\n\n                    // nested\n                    case JsonTokenType.StartArray:\n                        var first = ReadFirstString(ref reader);\n                        if (first != null)\n                            results.Add(first);","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/BCUninstaller/Bulk-Crap-Uninstaller/blob/608321de98e92297377b1eb69029af55c25504a1/source/UninstallTools/Factory/Json/DynamicStringArrayConverter.cs#L8-L44","documentation":"A JsonException thrown by `DynamicStringArrayConverter.Read` when the current JSON token is neither a string nor the start of an array. The converter is designed to accept either a single string or a string array for a property and normalize both into `string[]`; any other token type (number, object, boolean, null token) is invalid for that contract and is rejected.","triggerScenarios":"Deserializing a JSON document where a field declared as a string-or-string-array instead contains a number, boolean, nested object, or explicit null. This occurs in the uninstaller's JSON import paths (e.g. exporting/importing the app list) when the source JSON does not match the expected schema.","commonSituations":"Hand-edited or third-party-exported JSON with inconsistent value types; a schema change where a field that used to be a string is now an object; null values where the converter expects a token it can read.","solutions":["Inspect the offending JSON at the reported token and convert the value to a string or array of strings.","Re-export the data from a trusted source to ensure schema compliance.","Pre-process the JSON to coerce unexpected scalar values to strings before deserialization."],"exampleFix":"// before\n\"UninstallerString\": 12345\n// after\n\"UninstallerString\": \"12345\"","handlingStrategy":"validation","validationCode":"// Pre-validate the token type before the converter runs (schema check).\nusing var doc = JsonDocument.Parse(json);\nforeach (var prop in doc.RootElement.EnumerateObject())\n    if (prop.Value.ValueType is JsonValueType.Number or JsonValueType.False or JsonValueType.True or JsonValueType.Null)\n        /* coerce or reject scalar where string/array expected */","typeGuard":"bool IsStringOrArray(JsonElement el) => el.ValueType is JsonValueType.String or JsonValueType.Array;","tryCatchPattern":"try { var data = JsonSerializer.Deserialize<T>(json, options); }\ncatch (JsonException ex) when (ex.Message.Contains(\"Expected string or array token\"))\n{ /* log the offending property, sanitize/repair the JSON, retry */ }","preventionTips":["Validate the source JSON schema before deserialization.","Re-export from trusted sources to avoid type drift.","Coerce unexpected scalar values to strings during pre-processing.","Pin the exporter/importer to the same schema version."],"tags":["json","serialization","data-validation","uninstalltools"],"backgroundTag":null,"analyzedSha":"608321de98e92297377b1eb69029af55c25504a1","analyzedAt":"2026-08-13T12:17:35.389Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}