antlr/antlr4 · error · UnsupportedOperationException
Couldn't identify final state of the precedence rule prefix
Error message
Couldn't identify final state of the precedence rule prefix section.
What it means
When deserialization requests rule-bypass transitions for a parser ATN, the deserializer rewrites every rule. For a left-recursive rule it must find the StarLoopEntryState whose final transition reaches a LoopEndState that epsilon-transitions to RuleStopState; this state marks the end of the precedence-rule prefix. If that expected shape is absent, bypass generation cannot proceed safely.
Source
Thrown at runtime/Java/src/org/antlr/v4/runtime/atn/ATNDeserializer.java:312
}
if (!(state instanceof StarLoopEntryState)) {
continue;
}
ATNState maybeLoopEndState = state.transition(state.getNumberOfTransitions() - 1).target;
if (!(maybeLoopEndState instanceof LoopEndState)) {
continue;
}
if (maybeLoopEndState.epsilonOnlyTransitions && maybeLoopEndState.transition(0).target instanceof RuleStopState) {
endState = state;
break;
}
}
if (endState == null) {
throw new UnsupportedOperationException("Couldn't identify final state of the precedence rule prefix section.");
}
excludeTransition = ((StarLoopEntryState)endState).loopBackState.transition(0);
}
else {
endState = atn.ruleToStopState[i];
}
// all non-excluded transitions that currently target end state need to target blockEnd instead
for (ATNState state : atn.states) {
for (Transition transition : state.transitions) {
if (transition == excludeTransition) {
continue;
}
if (transition.target == endState) {
transition.target = bypassStop;
}View on GitHub (pinned to 7d5770395b)
Solutions
- Regenerate the parser with the same ANTLR version as the runtime and clean-build.
- Remove duplicate/conflicting ANTLR jars from the classpath.
- Do not manually edit or transform serialized ATN strings.
- If bypass alternatives are not required, use the normal ATN/parser path instead of getATNWithBypassAlts().
Example fix
// before ParseTreePattern p = parser.compileParseTreePattern(expr, MyParser.RULE_expr); // forces bypass ATN // after: regenerate parser/lexer with matching ANTLR version, then ParseTreePattern p = parser.compileParseTreePattern(expr, MyParser.RULE_expr);
Defensive patterns
Strategy: try-catch
Try / catch
try {
return parser.getATNWithBypassAlts();
} catch (UnsupportedOperationException e) {
throw new IllegalStateException("Parser ATN is incompatible with this runtime; regenerate parser sources", e);
} Prevention
- Regenerate parser and lexer together after ANTLR upgrades.
- Do not hand-transform serialized ATNs used for tree patterns.
- Keep parse-tree-pattern code on generated parsers matching the runtime.
When it happens
Trigger: Calling parser.getATNWithBypassAlts() or compileParseTreePattern() with an incompatible/corrupted parser ATN; deserializing custom or hand-transformed ATN data with generateRuleBypassTransitions=true; mixing serialized parser data from another ANTLR version.
Common situations: Parse-tree pattern matching, tree pattern compilation, version mismatches after upgrading ANTLR without regeneration, and custom ATN transformations that alter left-recursive rule structure.
Related errors
- Could not deserialize ATN with version %d (expected %d).
- The specified transition type is not valid.
- The specified state type %d is not valid.
- Serialized ATN data element[i] = v doesn't fit in 31 bits
- Cannot serialize a transition to a removed state.
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/fe5b9e7c2016e4ef.
Report an issue: GitHub.