antlr/antlr4 · critical · IllegalArgumentException
The specified lexer action type %s is not valid.
Error message
The specified lexer action type %s is not valid.
What it means
For lexer ATNs, lexerActionFactory constructs actions only for the built-in LexerActionType values CHANNEL, CUSTOM, MODE, MORE, POP_MODE, PUSH_MODE, SKIP, and TYPE. An unrecognized action type indicates incompatible or malformed serialized lexer action data. In practice this usually means lexer/runtime classes from different ANTLR versions are mixed.
Source
Thrown at runtime/Java/src/org/antlr/v4/runtime/atn/ATNDeserializer.java:586
return new LexerModeAction(data1);
case MORE:
return LexerMoreAction.INSTANCE;
case POP_MODE:
return LexerPopModeAction.INSTANCE;
case PUSH_MODE:
return new LexerPushModeAction(data1);
case SKIP:
return LexerSkipAction.INSTANCE;
case TYPE:
return new LexerTypeAction(data1);
default:
throw new IllegalArgumentException(String.format(Locale.getDefault(), "The specified lexer action type %s is not valid.", type));
}
}
/** Given a list of integers representing a serialized ATN, encode values too large to fit into 15 bits
* as two 16bit values. We use the high bit (0x8000_0000) to indicate values requiring two 16 bit words.
* If the high bit is set, we grab the next value and combine them to get a 31-bit value. The possible
* input int values are [-1,0x7FFF_FFFF].
*
* | compression/encoding | uint16 count | type |
* | -------------------------------------------- | ------------ | --------------- |
* | 0xxxxxxx xxxxxxxx | 1 | uint (15 bit) |
* | 1xxxxxxx xxxxxxxx yyyyyyyy yyyyyyyy | 2 | uint (16+ bits) |
* | 11111111 11111111 11111111 11111111 | 2 | int value -1 |
*
* This is only used (other than for testing) by {@link org.antlr.v4.codegen.model.SerializedJavaATN}
* to encode ints as char values for the java target, but it is convenient to combine it with the
* #decodeIntsEncodedAs16BitWords that follows as they are a pair (I did not want to introduce a new class
* into the runtime). Used only for Java Target.View on GitHub (pinned to 7d5770395b)
Solutions
- Align the ANTLR tool, generated lexer, and antlr4-runtime on one version.
- Regenerate all lexer/parser sources and clean-build.
- Inspect dependencies for duplicate or shaded ANTLR runtimes.
- Do not manually edit serialized lexer action records.
Example fix
// before: generated lexer from one ANTLR version, runtime from another new MyLexer(input); // after: regenerate MyLexer with the runtime's ANTLR version and remove duplicate runtime jars new MyLexer(input);
Defensive patterns
Strategy: try-catch
Try / catch
try {
return new ATNDeserializer(options).deserialize(serialized);
} catch (IllegalArgumentException e) {
throw new IllegalStateException("Lexer action data is incompatible with this ANTLR runtime", e);
} Prevention
- Use one ANTLR runtime version across generated lexers and application.
- Regenerate lexer sources when the runtime changes.
- Do not hand-edit serialized lexer action ordinals.
When it happens
Trigger: Deserializing a lexer ATN whose lexer-action ordinal was encoded by a different runtime/ANTLR build; corrupted serialized data causing an invalid enum/action code; or classpath shadowing that loads mismatched LexerActionType and ATNDeserializer classes.
Common situations: Multiple antlr4-runtime versions, stale generated lexers, shading conflicts, and custom serialized ATN data.
Related errors
- The specified lexer action type %s is not valid.
- Could not deserialize ATN with version %d (expected %d).
- The specified state type %d is not valid.
- Couldn't identify final state of the precedence rule prefix
- The specified transition type is not valid.
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/7cbb5dd6171a95b4.
Report an issue: GitHub.