JamesNK/Newtonsoft.Json · error · JsonException

Index {0} not valid on {1}.

Error message

Index {0} not valid on {1}.

What it means

Thrown by PathFilter.GetTokenIndex when a numeric index is applied to a token that is neither a JArray nor a JConstructor (e.g. a JObject or a scalar JValue), and ErrorWhenNoMatch is true. Indexing is only meaningful on ordered containers.

Source

Thrown at Src/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs:45

            else if (t is JConstructor c)
            {
                if (c.Count <= index)
                {
                    if (settings?.ErrorWhenNoMatch ?? false)
                    {
                        throw new JsonException("Index {0} outside the bounds of JConstructor.".FormatWith(CultureInfo.InvariantCulture, index));
                    }

                    return null;
                }

                return c[index];
            }
            else
            {
                if (settings?.ErrorWhenNoMatch ?? false)
                {
                    throw new JsonException("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, t.GetType().Name));
                }

                return null;
            }
        }

        protected static JToken? GetNextScanValue(JToken originalParent, JToken? container, JToken? value)
        {
            // step into container's values
            if (container != null && container.HasValues)
            {
                value = container.First;
            }
            else
            {
                // finished container, move to parent
                while (value != null && value != originalParent && value == value.Parent!.Last)
                {

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Use a property filter ($.name) instead of an index when the token is an object.
  2. Check token.Type before applying the index path, or disable ErrorWhenNoMatch.
  3. Validate the root token type (array vs object) before running positional queries.

Example fix

// before
token.SelectTokens("$[0]", new JsonSelectSettings { ErrorWhenNoMatch = true }); // token is JObject
// after
token.SelectTokens("$.name", new JsonSelectSettings { ErrorWhenNoMatch = true });
Defensive patterns

Strategy: type-guard

Validate before calling

static bool SupportsIndex(JToken token)
{
    return token is JArray || token is JConstructor;
}

Type guard

bool IsIndexable(JToken t) => t is JArray || t is JConstructor;

Try / catch

try { token.SelectTokens("$[0]", settings).ToList(); }
catch (JsonException ex) when (ex.Message.Contains("not valid on"))
{ /* token is not an array/constructor; switch to property access */ }

Prevention

When it happens

Trigger: Calling an index filter on a non-array token with strict matching. Example: token.SelectTokens("$[0]", new JsonSelectSettings { ErrorWhenNoMatch = true }) where token is a JObject. The path '$[0]' assumes array semantics on an object.

Common situations: Payload shape changed from array to object between API versions; the root token is an object but the path assumes an array; chained filters where an earlier filter unexpectedly returned a scalar; enabling strict matching on loosely-typed data.

Related errors


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