antlr/antlr4 · critical · IllegalArgumentException
The specified state type %d is not valid.
Error message
The specified state type %d is not valid.
What it means
ATNDeserializer.stateFactory accepts only known ATN state type codes: 1..12 for Basic through LoopEnd states (0 is handled earlier as an invalid/optimized-away marker). An unknown state type means the serialized state table does not match this runtime format.
Source
Thrown at runtime/Java/src/org/antlr/v4/runtime/atn/ATNDeserializer.java:552
protected ATNState stateFactory(int type, int ruleIndex) {
ATNState s;
switch (type) {
case ATNState.INVALID_TYPE: return null;
case ATNState.BASIC : s = new BasicState(); break;
case ATNState.RULE_START : s = new RuleStartState(); break;
case ATNState.BLOCK_START : s = new BasicBlockStartState(); break;
case ATNState.PLUS_BLOCK_START : s = new PlusBlockStartState(); break;
case ATNState.STAR_BLOCK_START : s = new StarBlockStartState(); break;
case ATNState.TOKEN_START : s = new TokensStartState(); break;
case ATNState.RULE_STOP : s = new RuleStopState(); break;
case ATNState.BLOCK_END : s = new BlockEndState(); break;
case ATNState.STAR_LOOP_BACK : s = new StarLoopbackState(); break;
case ATNState.STAR_LOOP_ENTRY : s = new StarLoopEntryState(); break;
case ATNState.PLUS_LOOP_BACK : s = new PlusLoopbackState(); break;
case ATNState.LOOP_END : s = new LoopEndState(); break;
default :
String message = String.format(Locale.getDefault(), "The specified state type %d is not valid.", type);
throw new IllegalArgumentException(message);
}
s.ruleIndex = ruleIndex;
return s;
}
protected LexerAction lexerActionFactory(LexerActionType type, int data1, int data2) {
switch (type) {
case CHANNEL:
return new LexerChannelAction(data1);
case CUSTOM:
return new LexerCustomAction(data1, data2);
case MODE:
return new LexerModeAction(data1);
case MORE:View on GitHub (pinned to 7d5770395b)
Solutions
- Regenerate the lexer/parser with the exact ANTLR version used at runtime.
- Ensure only one matching antlr4-runtime version is on the classpath.
- Pass the generated serialized ATN unchanged.
- For custom ATN formats, update both serializer and deserializer together.
Example fix
// before ATN atn = new ATNDeserializer().deserialize(customData); // after: pair custom data with the serializer/runtime that produced it, or use generated data ATN atn = new ATNDeserializer().deserialize(MyLexer._serializedATN.toCharArray());
Defensive patterns
Strategy: try-catch
Try / catch
try {
return new ATNDeserializer(options).deserialize(serialized);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Serialized ATN state table is corrupt or incompatible", e);
} Prevention
- Regenerate sources after ANTLR version changes.
- Resolve conflicting runtime jars before parsing.
- Do not emit custom state-type codes without updating the deserializer.
When it happens
Trigger: Deserializing malformed, misaligned, or incompatible serialized ATN state records; custom serialization that emits new state-type codes; or generated data from an incompatible ANTLR version.
Common situations: Version mismatches, stale generated sources, and custom ATN data manipulation.
Related errors
- Could not deserialize ATN with version %d (expected %d).
- Couldn't identify final state of the precedence rule prefix
- The specified transition type is not valid.
- The specified lexer action type %s is not valid.
- Serialized ATN data element[i] = v doesn't fit in 31 bits
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/9f24819c3aa2ef62.
Report an issue: GitHub.