{"record":{"id":"32f6391a8ce80449","repo":"antlr/antlr4","slug":"missing-element-after-s","errorCode":null,"errorMessage":"Missing element after %s","messagePattern":"Missing element after (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"runtime/Python3/src/antlr4/xpath/XPath.py","lineNumber":106,"sourceCode":"        tokenStream = CommonTokenStream(lexer)\n        try:\n            tokenStream.fill()\n        except LexerNoViableAltException as e:\n            pos = lexer.column\n            msg = \"Invalid tokens or characters at index %d in path '%s'\" % (pos, path)\n            raise Exception(msg, e)\n\n        tokens = iter(tokenStream.tokens)\n        elements = list()\n        for el in tokens:\n            invert = False\n            anywhere = False\n            # Check for path separators, if none assume root\n            if el.type in [XPathLexer.ROOT, XPathLexer.ANYWHERE]:\n                anywhere = el.type == XPathLexer.ANYWHERE\n                next_el = next(tokens, None)\n                if not next_el:\n                    raise Exception('Missing element after %s' % el.getText())\n                else:\n                    el = next_el\n            # Check for bangs\n            if el.type == XPathLexer.BANG:\n                invert = True\n                next_el = next(tokens, None)\n                if not next_el:\n                    raise Exception('Missing element after %s' % el.getText())\n                else:\n                    el = next_el\n            # Add searched element\n            if el.type in [XPathLexer.TOKEN_REF, XPathLexer.RULE_REF, XPathLexer.WILDCARD, XPathLexer.STRING]:\n                element = self.getXPathElement(el, anywhere)\n                element.invert = invert\n                elements.append(element)\n            elif el.type==Token.EOF:\n                break\n            else:","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Python3/src/antlr4/xpath/XPath.py#L88-L124","documentation":"Raised by XPath element parsing in the Python3 runtime when a '/' or '//' root/anywhere token is the last token in the path, so no element follows it. A separator must be followed by a rule name, token name, wildcard, or string.","triggerScenarios":"Calling XPath(parser, '/expr/') or XPath(parser, '//') — the trailing separator has no following element.","commonSituations":"Trailing slash habit from filesystem paths, or building paths by joining components with '/' and accidentally leaving a trailing separator.","solutions":["Remove the trailing '/' or '//' from the path","Follow every separator with a concrete element (rule name, token name, '*', or quoted string)","Strip trailing separators when constructing paths dynamically: path.rstrip('/')"],"exampleFix":"# before\nnodes = XPath.findAll(tree, \"//expr//\", parser)\n\n# after\nnodes = XPath.findAll(tree, \"//expr\", parser)","handlingStrategy":"validation","validationCode":"if xpath.rstrip() != xpath.rstrip('/'):\n    raise ValueError('XPath must not end with a separator')","typeGuard":null,"tryCatchPattern":"try:\n    nodes = XPath.findAll(tree, xpath, parser)\nexcept Exception as e:\n    if str(e).startswith('Missing element after'):\n        xpath = xpath.rstrip('/\\\\')  # retry once with trimmed path\n        nodes = XPath.findAll(tree, xpath, parser)","preventionTips":["Always end paths with an element, never a separator","Strip trailing separators from dynamically built paths"],"tags":["antlr","python","xpath","validation"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}