JamesNK/Newtonsoft.Json · error · JsonException

Index * not valid on {0}.

Error message

Index * not valid on {0}.

What it means

Thrown during JSONPath evaluation when a wildcard array indexer (the [*] form, where ArrayIndexFilter.Index is null) is applied to a token that is not a JArray or JConstructor, and error reporting is enabled. The filter expected an array to enumerate all children but encountered another node type (JObject, JValue, JProperty, etc.), so it reports 'Index * not valid on {TypeName}'.

Source

Thrown at Src/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs:37

                    if (v != null)
                    {
                        yield return v;
                    }
                }
                else
                {
                    if (t is JArray || t is JConstructor)
                    {
                        foreach (JToken v in t)
                        {
                            yield return v;
                        }
                    }
                    else
                    {
                        if (settings?.ErrorWhenNoMatch ?? false)
                        {
                            throw new JsonException("Index * not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name));
                        }
                    }
                }
            }
        }
    }
}

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Inspect the actual token type at the path before applying the [*] wildcard and use a property access for objects.
  2. Call SelectTokens without errorWhenNoMatch (or ErrorWhenNoMatch=false) so a missing/non-array simply yields zero results.
  3. Normalize the source JSON so the field is always an array (wrap singletons in a list at deserialization time).
  4. Verify the path points at a JArray using token["data"] is JArray before selecting.

Example fix

// before
token.SelectTokens("$.data[*]", errorWhenNoMatch: true);

// after
var data = token["data"];
if (data is JArray arr)
{
    foreach (var item in arr) { /* ... */ }
}
// else: data is a single object or null, handle accordingly
Defensive patterns

Strategy: type-guard

Validate before calling

// Confirm the node is an array before applying [*]
var node = token.SelectToken("$.data");
if (node is JArray)
{
    var items = token.SelectTokens("$.data[*]");
}

Type guard

static bool IsJsonArray(JToken? t) => t is JArray;

Prevention

When it happens

Trigger: Calling token.SelectTokens("$.data[*]", errorWhenNoMatch: true) or SelectTokens with JsonSelectSettings { ErrorWhenNoMatch = true } where the node at 'data' resolves to a JObject or scalar JValue instead of a JArray. The wildcard branch (ArrayIndexFilter.cs:26-38) only iterates JArray/JConstructor; anything else plus ErrorWhenNoMatch throws.

Common situations: The upstream JSON schema changed so a field that used to be an array is now a single object or null; an API returns a single object instead of a list when there is one item; assuming an array where a polymorphic single-value shape is returned.

Related errors


AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07). Data as JSON: /api/errors/a9b28a1ef97766b6. Report an issue: GitHub.