BCUninstaller/Bulk-Crap-Uninstaller · error · JsonException

Expected string or array token but got

Error message

Expected string or array token but got {reader.TokenType}

What it means

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.

Solutions

  1. Inspect the offending JSON at the reported token and convert the value to a string or array of strings.
  2. Re-export the data from a trusted source to ensure schema compliance.
  3. Pre-process the JSON to coerce unexpected scalar values to strings before deserialization.

Example fix

// before
"UninstallerString": 12345
// after
"UninstallerString": "12345"
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate the token type before the converter runs (schema check).
using var doc = JsonDocument.Parse(json);
foreach (var prop in doc.RootElement.EnumerateObject())
    if (prop.Value.ValueType is JsonValueType.Number or JsonValueType.False or JsonValueType.True or JsonValueType.Null)
        /* coerce or reject scalar where string/array expected */

Type guard

bool IsStringOrArray(JsonElement el) => el.ValueType is JsonValueType.String or JsonValueType.Array;

Try / catch

try { var data = JsonSerializer.Deserialize<T>(json, options); }
catch (JsonException ex) when (ex.Message.Contains("Expected string or array token"))
{ /* log the offending property, sanitize/repair the JSON, retry */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of BCUninstaller/Bulk-Crap-Uninstaller@608321de98 (2026-08-13). Data as JSON: /api/errors/fdee1e3fe55eedf9. Report an issue: GitHub.

Appendix: source

Thrown at source/UninstallTools/Factory/Json/DynamicStringArrayConverter.cs:26

    /// <summary>
    /// Handle JSON string array entry that has one dimension less or more.
    /// </summary>
    internal class DynamicStringArrayConverter : JsonConverter<string[]>
    {
        public override string[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            // 0-dimension
            if (reader.TokenType == JsonTokenType.String)
                return new[] { reader.GetString() };

            if (reader.TokenType == JsonTokenType.StartArray)
            {
                var results = new List<string>();
                ReadStrings(ref reader, results);
                return results.ToArray();
            }

            throw new JsonException($"Expected string or array token but got {reader.TokenType}");
        }

        private static void ReadStrings(ref Utf8JsonReader reader, List<string> results)
        {
            while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
            {
                switch (reader.TokenType)
                {
                    // normal
                    case JsonTokenType.String:
                        results.Add(reader.GetString());
                        break;

                    // nested
                    case JsonTokenType.StartArray:
                        var first = ReadFirstString(ref reader);
                        if (first != null)
                            results.Add(first);

View on GitHub (pinned to 608321de98)