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

  1. Regenerate the lexer/parser with the exact ANTLR version used at runtime.
  2. Ensure only one matching antlr4-runtime version is on the classpath.
  3. Pass the generated serialized ATN unchanged.
  4. 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

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


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