Humanizr/Humanizer · error · InvalidOperationException

Indexed string arrays require non-negative integer keys. Inv

Error message

Indexed string arrays require non-negative integer keys. Invalid key '{property.Name}'.

What it means

CreateNumericSlotStringArrayExpression (GenerationHelpers.cs:310-313) handles the indexed-mapping form of a string array and requires every key to be a non-negative integer. A word key, a negative index, or a non-numeric key fails int.TryParse or the index<0 check.

Source

Thrown at src/Humanizer.SourceGenerators/Common/GenerationHelpers.cs:312

        }

        builder.Append(" }");
        return builder.ToString();
    }

    static string CreateNumericSlotStringArrayExpression(JsonElement objectElement)
    {
        if (!objectElement.EnumerateObject().Any())
        {
            return "Array.Empty<string>()";
        }

        var indexedValues = new SortedDictionary<int, string>();
        foreach (var property in objectElement.EnumerateObject())
        {
            if (!int.TryParse(property.Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var index) || index < 0)
            {
                throw new InvalidOperationException($"Indexed string arrays require non-negative integer keys. Invalid key '{property.Name}'.");
            }

            if (property.Value.ValueKind != JsonValueKind.String)
            {
                throw new InvalidOperationException($"Indexed string arrays require string values. Property '{property.Name}' was {property.Value.ValueKind}.");
            }

            indexedValues[index] = property.Value.GetString()!;
        }

        var builder = new StringBuilder("new string[] { ");
        var first = true;
        var lastIndex = indexedValues.Keys.Max();

        for (var index = 0; index <= lastIndex; index++)
        {
            if (!first)
            {

View on GitHub (pinned to ffc2b77c0f)

Solutions

  1. Use integer keys only: {2: 'twenty', 3: 'thirty'}.
  2. Ensure all keys are >= 0 (leading empty slots are represented by index gaps, not negatives).
  3. If a word-keyed mapping is intended, switch the field to the plain-array form instead.

Example fix

# before
tensMap:
  two: 'twenty'
  three: 'thirty'
# after
tensMap:
  2: 'twenty'
  3: 'thirty'
Defensive patterns

Strategy: validation

Validate before calling

// Indexed string-array keys must be non-negative integers (C#)
foreach (var prop in obj.EnumerateObject())
    if (!int.TryParse(prop.Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var i) || i < 0)
        throw new InvalidOperationException($"Invalid index key '{prop.Name}'");

Type guard

static bool IsValidIndexKey(string name) =>
    int.TryParse(name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var i) && i >= 0;

Prevention

When it happens

Trigger: An indexed mapping uses word keys ({two: 'twenty'}) or negative keys ({-1: 'x'}) instead of non-negative integer keys.

Common situations: Authoring tensMap/unitsMap with readable word keys instead of numeric indices; copy-paste from a different mapping style.

Related errors


AI-assisted analysis of Humanizr/Humanizer@ffc2b77c0f (2026-08-13). Data as JSON: /api/errors/53f5fa69fa77a2dc. Report an issue: GitHub.