{"record":{"id":"fcb748abdf6a6c16","repo":"antlr/antlr4","slug":"missing-path-element-at-end-of-path-fcb748","errorCode":null,"errorMessage":"Missing path element at end of path","messagePattern":"Missing path element at end of path","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"runtime/CSharp/src/Tree/Xpath/XPath.cs","lineNumber":204,"sourceCode":"        /// or\n        /// <c>ID</c>\n        /// or\n        /// <c>expr</c>\n        /// to a path\n        /// element.\n        /// <paramref name=\"anywhere\"/>\n        /// is\n        /// <see langword=\"true\"/>\n        /// if\n        /// <c>//</c>\n        /// precedes the\n        /// word.\n        /// </summary>\n        protected internal virtual XPathElement GetXPathElement(IToken wordToken, bool anywhere)\n        {\n            if (wordToken.Type == TokenConstants.EOF)\n            {\n                throw new ArgumentException(\"Missing path element at end of path\");\n            }\n            string word = wordToken.Text;\n            int ttype = parser.GetTokenType(word);\n            int ruleIndex = parser.GetRuleIndex(word);\n            switch (wordToken.Type)\n            {\n                case XPathLexer.Wildcard:\n                {\n                    return anywhere ? new XPathWildcardAnywhereElement() : (XPathElement)new XPathWildcardElement();\n                }\n\n                case XPathLexer.TokenRef:\n                case XPathLexer.String:\n                {\n                    if (ttype == TokenConstants.InvalidType)\n                    {\n                        throw new ArgumentException(word + \" at index \" + wordToken.StartIndex + \" isn't a valid token name\");\n                    }","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/CSharp/src/Tree/Xpath/XPath.cs#L186-L222","documentation":"GetXPathElement() is called with the token that follows a '/' or '//'. If that token is EOF, the path ends immediately after a separator, so no rule, token, or wildcard element exists. ANTLR rejects such paths because every separator must introduce an element.","triggerScenarios":"Paths such as \"/prog/\", \"//stmt//\", or \"/prog/!\" end with a separator (or separator plus inversion) and then EOF. The same occurs when a loop appends '/' after the last component.","commonSituations":"File-system style paths with a harmless trailing slash are passed to XPath; paths are built by joining components with '/' and the final delimiter is not trimmed; or an optional element is omitted but its separator remains.","solutions":["Remove the trailing '/', '//', or '/!' from the XPath string.","If the final component was intended, add its name or '*' after the separator.","Trim trailing separators before constructing XPath when assembling paths dynamically."],"exampleFix":"// before\nvar xpath = \"/program/\";\n\n// after\nvar xpath = \"/program\";","handlingStrategy":"validation","validationCode":"static bool HasElementAfterEverySeparator(string path) {\n    return !path.EndsWith(\"/\") && !path.EndsWith(\"//\") && !path.EndsWith(\"!\");\n}","typeGuard":null,"tryCatchPattern":"try { var p = new Antlr4.Runtime.Tree.Xpath.XPath(parser, xpath); }\ncatch (ArgumentException ex) when (ex.Message == \"Missing path element at end of path\") { /* trim separator or add element */ }","preventionTips":["Trim trailing '/' and '!' before constructing XPath.","Use string.Join(\"/\", components) instead of appending delimiters manually.","Add unit tests for dynamically generated XPath strings."],"tags":["antlr","csharp","xpath","input-validation"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}