antlr/antlr4 · error · IllegalArgumentException
Invalid state number.
Error message
Invalid state number.
What it means
ATN.getExpectedTokens(stateNumber, context) uses stateNumber as an index into the ATN state list. A negative value or a value at least atn.states.size() cannot identify an ATN state, so the method rejects it before computing the follow set.
Source
Thrown at runtime/Java/src/org/antlr/v4/runtime/atn/ATN.java:168
* The big difference is that with just the input, the parser could
* land right in the middle of a lookahead decision. Getting
* all *possible* tokens given a partial input stream is a separate
* computation. See https://github.com/antlr/antlr4/issues/1428
*
* For this function, we are specifying an ATN state and call stack to compute
* what token(s) can come next and specifically: outside of a lookahead decision.
* That is what you want for error reporting and recovery upon parse error.
*
* @param stateNumber the ATN state number
* @param context the full parse context
* @return The set of potentially valid input symbols which could follow the
* specified state in the specified context.
* @throws IllegalArgumentException if the ATN does not contain a state with
* number {@code stateNumber}
*/
public IntervalSet getExpectedTokens(int stateNumber, RuleContext context) {
if (stateNumber < 0 || stateNumber >= states.size()) {
throw new IllegalArgumentException("Invalid state number.");
}
RuleContext ctx = context;
ATNState s = states.get(stateNumber);
IntervalSet following = nextTokens(s);
if (!following.contains(Token.EPSILON)) {
return following;
}
IntervalSet expected = new IntervalSet();
expected.addAll(following);
expected.remove(Token.EPSILON);
while (ctx != null && ctx.invokingState >= 0 && following.contains(Token.EPSILON)) {
ATNState invokingState = states.get(ctx.invokingState);
RuleTransition rt = (RuleTransition)invokingState.transition(0);
following = nextTokens(rt.followState);
expected.addAll(following);
expected.remove(Token.EPSILON);View on GitHub (pinned to 7d5770395b)
Solutions
- Validate 0 <= stateNumber < atn.states.size() before the call.
- Prefer parser.getExpectedTokens() or RecognitionException.getExpectedTokens(), which use the recognizer's current state.
- Ensure the ATN, parser, context, and generated code all come from the same generated parser and ANTLR version.
- Treat -1 as unknown state and report a generic error instead of calling the API.
Example fix
// before
int state = ctx.getRuleIndex(); // wrong: rule index, not ATN state
IntervalSet expected = atn.getExpectedTokens(state, ctx);
// after
int state = parser.getState();
if (state >= 0 && state < atn.states.size()) {
IntervalSet expected = atn.getExpectedTokens(state, parser.getContext());
} Defensive patterns
Strategy: validation
Validate before calling
static boolean isValidAtnState(ATN atn, int stateNumber) {
return stateNumber >= 0 && stateNumber < atn.states.size();
} Try / catch
try {
return atn.getExpectedTokens(stateNumber, context);
} catch (IllegalArgumentException e) {
return new IntervalSet(); // or report that the state is unknown
} Prevention
- Never substitute rule indexes or token types for ATN state numbers.
- Use parser.getExpectedTokens() where possible.
- Use parser, ATN, and context objects from the same generated version.
When it happens
Trigger: Passing a rule index, token type, or generated context constant where an ATN state number is expected; passing -1 from an exception whose offending state is unknown; or using a state number obtained from a different parser/ATN version.
Common situations: Custom error reporters that manually call getATN().getExpectedTokens(), mixing generated parser classes from different ANTLR builds, and code that assumes getOffendingState()/getState() is always valid.
Related errors
- Serialized ATN data element[i] = v doesn't fit in 31 bits
- index cannot be negative
- ANTLR 4 caught {} build errors.
- cannot consume EOF
- The ATN must be a lexer ATN.
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/c2c126a32be2f053.
Report an issue: GitHub.