antlr/antlr4 · error · IllegalArgumentException

at index isn't a valid token name

Error message

{word} at index {startIndex} isn't a valid token name

What it means

For an uppercase token reference (or string literal) in an XPath path, the parser's vocabulary is consulted via getTokenType(word); when it returns Token.INVALID_TYPE the name is unknown to that grammar, and IllegalArgumentException is thrown with the word and its index in the path.

Solutions

  1. Use the exact token name from the generated parser (check parser.getVocabulary() or the generated *.tokens file)
  2. Remember case convention: TOKEN refs are uppercase, rule refs lowercase
  3. If the grammar changed, regenerate and re-check names before running XPath queries

Example fix

// before
XPath.findAll(tree, "/IDENT", parser); // grammar has ID, not IDENT

// after
XPath.findAll(tree, "/ID", parser);
Defensive patterns

Strategy: validation

Validate before calling

boolean knownToken = parser.getVocabulary().getSymbolicName(parser.getTokenType(word)) != null;
// stronger: int t = parser.getTokenType(word); boolean ok = t != Token.INVALID_TYPE;

Try / catch

try { XPath.findAll(tree, path, parser); } catch (IllegalArgumentException e) { /* message names the invalid token and index; correct the query */ }

Prevention

When it happens

Trigger: XPath.findAll(tree, "/IDENT/expr", parser) where the grammar defines no token named IDENT (maybe it is called ID); also literal text like 'foo:"bar"' where foo is not a token.

Common situations: Querying a parse tree with token names from a different grammar version; guessing token names instead of checking the generated vocabulary; using a rule name in uppercase (case matters: uppercase = token, lowercase = rule).

Related errors


AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14). Data as JSON: /api/errors/3c40731ce47c1925. Report an issue: GitHub.

Appendix: source

Thrown at runtime/Java/src/org/antlr/v4/runtime/tree/xpath/XPath.java:172

	 * element. {@code anywhere} is {@code true} if {@code //} precedes the
	 * word.
	 */
	protected XPathElement getXPathElement(Token wordToken, boolean anywhere) {
		if ( wordToken.getType()==Token.EOF ) {
			throw new IllegalArgumentException("Missing path element at end of path");
		}
		String word = wordToken.getText();
		int ttype = parser.getTokenType(word);
		int ruleIndex = parser.getRuleIndex(word);
		switch ( wordToken.getType() ) {
			case XPathLexer.WILDCARD :
				return anywhere ?
					new XPathWildcardAnywhereElement() :
					new XPathWildcardElement();
			case XPathLexer.TOKEN_REF :
			case XPathLexer.STRING :
				if ( ttype==Token.INVALID_TYPE ) {
					throw new IllegalArgumentException(word+
													   " at index "+
													   wordToken.getStartIndex()+
													   " isn't a valid token name");
				}
				return anywhere ?
					new XPathTokenAnywhereElement(word, ttype) :
					new XPathTokenElement(word, ttype);
			default :
				if ( ruleIndex==-1 ) {
					throw new IllegalArgumentException(word+
													   " at index "+
													   wordToken.getStartIndex()+
													   " isn't a valid rule name");
				}
				return anywhere ?
					new XPathRuleAnywhereElement(word, ruleIndex) :
					new XPathRuleElement(word, ruleIndex);
		}

View on GitHub (pinned to 7d5770395b)