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

  1. Regenerate the parser with the same ANTLR version as the runtime and clean-build.
  2. Remove duplicate/conflicting ANTLR jars from the classpath.
  3. Do not manually edit or transform serialized ATN strings.
  4. 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

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


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