{"record":{"id":"4f465365e233d3fe","repo":"antlr/antlr4","slug":"word-at-index-startindex-isn-t-a-valid-rule-na","errorCode":null,"errorMessage":"{word} at index {startIndex} isn't a valid rule name","messagePattern":"(.+?) at index (.+?) isn't a valid rule name","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"runtime/Java/src/org/antlr/v4/runtime/tree/xpath/XPath.java","lineNumber":182,"sourceCode":"\t\tswitch ( wordToken.getType() ) {\n\t\t\tcase XPathLexer.WILDCARD :\n\t\t\t\treturn anywhere ?\n\t\t\t\t\tnew XPathWildcardAnywhereElement() :\n\t\t\t\t\tnew XPathWildcardElement();\n\t\t\tcase XPathLexer.TOKEN_REF :\n\t\t\tcase XPathLexer.STRING :\n\t\t\t\tif ( ttype==Token.INVALID_TYPE ) {\n\t\t\t\t\tthrow new IllegalArgumentException(word+\n\t\t\t\t\t\t\t\t\t\t\t\t\t   \" at index \"+\n\t\t\t\t\t\t\t\t\t\t\t\t\t   wordToken.getStartIndex()+\n\t\t\t\t\t\t\t\t\t\t\t\t\t   \" isn't a valid token name\");\n\t\t\t\t}\n\t\t\t\treturn anywhere ?\n\t\t\t\t\tnew XPathTokenAnywhereElement(word, ttype) :\n\t\t\t\t\tnew XPathTokenElement(word, ttype);\n\t\t\tdefault :\n\t\t\t\tif ( ruleIndex==-1 ) {\n\t\t\t\t\tthrow new IllegalArgumentException(word+\n\t\t\t\t\t\t\t\t\t\t\t\t\t   \" at index \"+\n\t\t\t\t\t\t\t\t\t\t\t\t\t   wordToken.getStartIndex()+\n\t\t\t\t\t\t\t\t\t\t\t\t\t   \" isn't a valid rule name\");\n\t\t\t\t}\n\t\t\t\treturn anywhere ?\n\t\t\t\t\tnew XPathRuleAnywhereElement(word, ruleIndex) :\n\t\t\t\t\tnew XPathRuleElement(word, ruleIndex);\n\t\t}\n\t}\n\n\n\tpublic static Collection<ParseTree> findAll(ParseTree tree, String xpath, Parser parser) {\n\t\tXPath p = new XPath(parser, xpath);\n\t\treturn p.evaluate(tree);\n\t}\n\n\t/**\n\t * Return a list of all nodes starting at {@code t} as root that satisfy the","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Java/src/org/antlr/v4/runtime/tree/xpath/XPath.java#L164-L200","documentation":"For a lowercase reference in an XPath path, parser.getRuleIndex(word) returning -1 means no rule with that name exists in the grammar. IllegalArgumentException reports the word and its start index in the path string.","triggerScenarios":"XPath.findAll(tree, \"/statement/expression\", parser) when the grammar's rule is named expr, not expression.","commonSituations":"Rule renamed between grammar versions while XPath queries kept the old name; writing queries from the language spec instead of the actual grammar file; querying a tree produced by a different parser than the one passed in.","solutions":["Verify the rule name against the grammar / generated parser: Arrays.asList(parser.getRuleNames()).contains(word)","Ensure the parser instance passed to XPath is the same grammar that produced the tree","Regenerate queries (or centralize them as constants) when rules are renamed"],"exampleFix":"// before\nXPath.findAll(tree, \"/statement/expression\", parser);\n\n// after\nXPath.findAll(tree, \"/statement/expr\", parser); // rule is 'expr' in the grammar","handlingStrategy":"validation","validationCode":"boolean knownRule = Arrays.asList(parser.getRuleNames()).contains(word);","typeGuard":null,"tryCatchPattern":"try { XPath.findAll(tree, path, parser); } catch (IllegalArgumentException e) { /* message names the invalid rule and index; fix the name */ }","preventionTips":["Pass the same parser (grammar) that built the tree","Re-check rule names after grammar refactors"],"tags":["antlr","xpath","rule-names","java"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}