{"record":{"id":"b2db9121441f3f16","repo":"JamesNK/Newtonsoft.Json","slug":"unexpected-character-while-parsing-path","errorCode":null,"errorMessage":"Unexpected character while parsing path: ","messagePattern":"Unexpected character while parsing path: ","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"Src/Newtonsoft.Json/Linq/JsonPath/JPath.cs","lineNumber":88,"sourceCode":"                // only increment position for \"$.\" or \"$[\"\n                // otherwise assume property that starts with $\n                char c = _expression[_currentIndex + 1];\n                if (c == '.' || c == '[')\n                {\n                    _currentIndex++;\n                    currentPartStartIndex = _currentIndex;\n                }\n            }\n\n            if (!ParsePath(Filters, currentPartStartIndex, false))\n            {\n                int lastCharacterIndex = _currentIndex;\n\n                EatWhitespace();\n\n                if (_currentIndex < _expression.Length)\n                {\n                    throw new JsonException(\"Unexpected character while parsing path: \" + _expression[lastCharacterIndex]);\n                }\n            }\n        }\n\n        private bool ParsePath(List<PathFilter> filters, int currentPartStartIndex, bool query)\n        {\n            bool scan = false;\n            bool followingIndexer = false;\n            bool followingDot = false;\n\n            bool ended = false;\n            while (_currentIndex < _expression.Length && !ended)\n            {\n                char currentChar = _expression[_currentIndex];\n\n                switch (currentChar)\n                {\n                    case '[':","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/JamesNK/Newtonsoft.Json/blob/4f73e74372445108d2c1bda37b36e6f5e43402e0/Src/Newtonsoft.Json/Linq/JsonPath/JPath.cs#L70-L106","documentation":"Thrown by the JPath parser when, after parsing the main path expression, there is leftover non-whitespace content that the parser could not consume. ParseMain calls ParsePath, and if it returns false (did not reach the end) while trailing characters remain, the unexpected character is reported. This is a JSONPath syntax error detected at path construction time.","triggerScenarios":"Passing a malformed JSONPath to SelectToken/SelectTokens, e.g. token.SelectToken(\"$.data.#foo\") or \"$.data @x\" where an illegal character appears that is not a valid path delimiter or field character. The reported character is _expression[lastCharacterIndex].","commonSituations":"Dynamically building path strings with unescaped special characters; mixing JSONPath syntax with JSON Pointer or other query dialects; copy/paste typos in a path literal.","solutions":["Inspect the exact character reported in the message and remove or escape it.","Validate the path against the supported JSONPath grammar (fields, dots, [index], ['field'], [*], [?()], recursive '..').","When building paths dynamically, sanitize/quote property names with single quotes inside indexers."],"exampleFix":"// before\ntoken.SelectToken(\"$.data.#foo\");\n\n// after\ntoken.SelectToken(\"$.data.foo\");","handlingStrategy":"validation","validationCode":"// Validate path syntax against allowed characters before querying\nstatic bool LooksLikeValidPath(string path)\n{\n    foreach (char c in path)\n    {\n        if (!(char.IsLetterOrDigit(c) || c == '.' || c == '[' || c == ']' ||\n              c == '\\'' || c == '*' || c == ',' || c == ':' || c == '(' ||\n              c == ')' || c == '?' || c == '@' || c == '$' || c == ' ' ||\n              c == '-' || c == '=' || c == '<' || c == '>' || c == '!' ||\n              c == '|' || c == '&'))\n            return false;\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    token.SelectToken(path);\n}\ncatch (JsonException ex) when (ex.Message.StartsWith(\"Unexpected character while parsing path\"))\n{\n    // surface a clear error to the caller with the offending path\n}","preventionTips":["Never interpolate untrusted input directly into a JSONPath string.","Quote property names with single quotes inside indexers.","Unit-test dynamically built paths against the supported grammar."],"tags":["jsonpath","parse-error","syntax"],"analyzedSha":"4f73e74372445108d2c1bda37b36e6f5e43402e0","analyzedAt":"2026-08-07T06:10:08.596Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}