antlr/antlr4 · error · FailedPredicateException

precpred(_ctx, %d)

Error message

precpred(_ctx, %d)

What it means

ParserInterpreter throws FailedPredicateException("precpred(_ctx, N)") when it walks a precedence-predicate transition and the runtime predicate test precpred(ctx, N) returns false — i.e. the parse context's precedence is too low for the alternative being entered (left-recursive rule semantics). The formatted message names the precedence level that failed. In a normal generated parser the adaptivePredict machinery avoids entering such alternatives, so this fires when the interpreter follows an ATN path the prediction would have rejected.

Source

Thrown at runtime/Java/src/org/antlr/v4/runtime/ParserInterpreter.java:289

				}
				break;

			case Transition.PREDICATE:
				PredicateTransition predicateTransition = (PredicateTransition)transition;
				if (!sempred(_ctx, predicateTransition.ruleIndex, predicateTransition.predIndex)) {
					throw new FailedPredicateException(this);
				}

				break;

			case Transition.ACTION:
				ActionTransition actionTransition = (ActionTransition)transition;
				action(_ctx, actionTransition.ruleIndex, actionTransition.actionIndex);
				break;

			case Transition.PRECEDENCE:
				if (!precpred(_ctx, ((PrecedencePredicateTransition)transition).precedence)) {
					throw new FailedPredicateException(this, String.format("precpred(_ctx, %d)", ((PrecedencePredicateTransition)transition).precedence));
				}
				break;

			default:
				throw new UnsupportedOperationException("Unrecognized ATN transition type.");
		}

		setState(transition.target.stateNumber);
	}

	/** Method visitDecisionState() is called when the interpreter reaches
	 *  a decision state (instance of DecisionState). It gives an opportunity
	 *  for subclasses to track interesting things.
	 */
	protected int visitDecisionState(DecisionState p) {
		int predictedAlt = 1;
		if ( p.getNumberOfTransitions()>1 ) {
			getErrorHandler().sync(this);

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Ensure the serialized ATN and the runtime come from the same ANTLR version (regenerate/re-serialize)
  2. Catch FailedPredicateException and inspect e.getCtx()/e.getPredicate() to identify which precedence level failed
  3. Prefer generated parsers over ParserInterpreter when possible — prediction in generated code prunes these alternatives correctly
  4. Validate the grammar's precedence structure (checkLeftRecursion output from the tool) before interpreting it

Example fix

// before
parserInterpreter.expression(); // throws FailedPredicateException mid-parse

// after
try { parserInterpreter.expression(); }
catch (FailedPredicateException e) {
  errors.add("precedence predicate failed: " + e.getMessage()
    + " at " + e.getOffendingToken().getText());
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  parserInterpreter.startRule();
} catch (FailedPredicateException e) {
  // message is 'precpred(_ctx, N)'; ctx and offending token identify the spot
  errors.add(e.getMessage() + " at line " + e.getOffendingToken().getLine());
}

Prevention

When it happens

Trigger: Running a grammar with left-recursive expression rules through ParserInterpreter (grammar loaded at runtime, not generated code); corrupted or version-mismatched serialized ATN where precedence transitions no longer match rule contexts; manually driving visitState/transition logic.

Common situations: Generic grammar-runner tools and IDE plugins that interpret grammars; deserializing an ATN produced by a different ANTLR version than the runtime interpreting it; precedence-climbing expression grammars (expr: expr '*' expr | expr '+' expr | INT with precedence options).

Related errors


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