{"record":{"id":"e239fa3e903cc6c1","repo":"JamesNK/Newtonsoft.Json","slug":"index-0-not-valid-on-1","errorCode":null,"errorMessage":"Index {0} not valid on {1}.","messagePattern":"Index (.+?) not valid on (.+?)\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"Src/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs","lineNumber":45,"sourceCode":"            else if (t is JConstructor c)\n            {\n                if (c.Count <= index)\n                {\n                    if (settings?.ErrorWhenNoMatch ?? false)\n                    {\n                        throw new JsonException(\"Index {0} outside the bounds of JConstructor.\".FormatWith(CultureInfo.InvariantCulture, index));\n                    }\n\n                    return null;\n                }\n\n                return c[index];\n            }\n            else\n            {\n                if (settings?.ErrorWhenNoMatch ?? false)\n                {\n                    throw new JsonException(\"Index {0} not valid on {1}.\".FormatWith(CultureInfo.InvariantCulture, index, t.GetType().Name));\n                }\n\n                return null;\n            }\n        }\n\n        protected static JToken? GetNextScanValue(JToken originalParent, JToken? container, JToken? value)\n        {\n            // step into container's values\n            if (container != null && container.HasValues)\n            {\n                value = container.First;\n            }\n            else\n            {\n                // finished container, move to parent\n                while (value != null && value != originalParent && value == value.Parent!.Last)\n                {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/JamesNK/Newtonsoft.Json/blob/4f73e74372445108d2c1bda37b36e6f5e43402e0/Src/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs#L27-L63","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use a property filter ($.name) instead of an index when the token is an object.","Check token.Type before applying the index path, or disable ErrorWhenNoMatch.","Validate the root token type (array vs object) before running positional queries."],"exampleFix":"// before\ntoken.SelectTokens(\"$[0]\", new JsonSelectSettings { ErrorWhenNoMatch = true }); // token is JObject\n// after\ntoken.SelectTokens(\"$.name\", new JsonSelectSettings { ErrorWhenNoMatch = true });","handlingStrategy":"type-guard","validationCode":"static bool SupportsIndex(JToken token)\n{\n    return token is JArray || token is JConstructor;\n}","typeGuard":"bool IsIndexable(JToken t) => t is JArray || t is JConstructor;","tryCatchPattern":"try { token.SelectTokens(\"$[0]\", settings).ToList(); }\ncatch (JsonException ex) when (ex.Message.Contains(\"not valid on\"))\n{ /* token is not an array/constructor; switch to property access */ }","preventionTips":["Verify the root token type before running positional index paths.","Keep ErrorWhenNoMatch off for loosely-typed payloads."],"tags":["jsonpath","json","jobject","jpath","type-mismatch"],"analyzedSha":"4f73e74372445108d2c1bda37b36e6f5e43402e0","analyzedAt":"2026-08-07T06:10:08.596Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}