antlr/antlr4 · error · IllegalArgumentException
The specified lexer action type %s is not valid.
Error message
The specified lexer action type %s is not valid.
What it means
ATNSerializer.addLexerActions serializes only the built-in LexerActionType cases. If atn.lexerActions contains a LexerAction whose getActionType() is not recognized by this switch, serialization cannot emit a valid action record and throws IllegalArgumentException. This points to a custom/future action type or mismatched runtime classes.
Source
Thrown at runtime/Java/src/org/antlr/v4/runtime/atn/ATNSerializer.java:145
mode = ((LexerPushModeAction)action).getMode();
data.add(mode);
data.add(0);
break;
case SKIP:
data.add(0);
data.add(0);
break;
case TYPE:
int type = ((LexerTypeAction)action).getType();
data.add(type);
data.add(0);
break;
default:
String message = String.format(Locale.getDefault(), "The specified lexer action type %s is not valid.", action.getActionType());
throw new IllegalArgumentException(message);
}
}
}
}
private void addDecisionStartStates() {
int ndecisions = atn.decisionToState.size();
data.add(ndecisions);
for (DecisionState decStartState : atn.decisionToState) {
data.add(decStartState.stateNumber);
}
}
private void addEdges(int nedges, Map<IntervalSet, Integer> setIndices) {
data.add(nedges);
for (ATNState s : atn.states) {
if ( s==null ) {
// might be optimized awayView on GitHub (pinned to 7d5770395b)
Solutions
- Represent custom behavior with LexerCustomAction instead of a new LexerActionType.
- If forking ANTLR, update LexerActionType, ATNSerializer, and ATNDeserializer together.
- Ensure every LexerAction class comes from the same runtime jar as ATNSerializer.
- Validate each action type against the built-in set before serialization.
Example fix
// before atn.lexerActions[i] = customActionWithUnsupportedType; IntegerList data = ATNSerializer.getSerialized(atn); // after atn.lexerActions[i] = new LexerCustomAction(ruleIndex, actionIndex); IntegerList data = ATNSerializer.getSerialized(atn);
Defensive patterns
Strategy: validation
Validate before calling
static boolean usesBuiltInLexerActionType(LexerAction action) {
switch (action.getActionType()) {
case CHANNEL:
case CUSTOM:
case MODE:
case MORE:
case POP_MODE:
case PUSH_MODE:
case SKIP:
case TYPE:
return true;
default:
return false;
}
} Try / catch
try {
return ATNSerializer.getSerialized(atn);
} catch (IllegalArgumentException e) {
throw new IllegalStateException("ATN contains a lexer action type this serializer cannot write", e);
} Prevention
- Use LexerCustomAction for application-specific behavior.
- Keep custom LexerAction implementations out of serialized ATNs.
- If extending the format, change enum, serializer, and deserializer together.
When it happens
Trigger: Calling ATNSerializer.getSerialized(atn) after inserting a custom LexerAction implementation or an action loaded from an incompatible ANTLR runtime; running with classpath shadowing that mixes LexerAction implementations and serializer versions.
Common situations: Custom lexer runtime extensions, experimental ANTLR forks, and multiple/conflicting antlr4-runtime jars.
Related errors
- The specified lexer action type %s is not valid.
- 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 state type %d is not valid.
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/c4bf4e6cdc6486bd.
Report an issue: GitHub.