antlr/antlr4 · error · UnsupportedOperationException

there is no serialized ATN

Error message

there is no serialized ATN

What it means

Thrown by Recognizer.getSerializedATN(), which the base class implements by throwing because only generated recognizers embed the serialized ATN string. Interpreter-based recognizers are built from a deserialized ATN and deliberately do not retain the serialization. Any tooling that asks a recognizer for its serialized ATN will fail on non-generated instances.

Source

Thrown at runtime/Java/src/org/antlr/v4/runtime/Recognizer.java:129

			return result;
		}
	}

	public int getTokenType(String tokenName) {
		Integer ttype = getTokenTypeMap().get(tokenName);
		if ( ttype!=null ) return ttype;
		return Token.INVALID_TYPE;
	}

	/**
	 * If this recognizer was generated, it will have a serialized ATN
	 * representation of the grammar.
	 *
	 * <p>For interpreters, we don't know their serialized ATN despite having
	 * created the interpreter from it.</p>
	 */
	public String getSerializedATN() {
		throw new UnsupportedOperationException("there is no serialized ATN");
	}

	/** For debugging and other purposes, might want the grammar name.
	 *  Have ANTLR generate an implementation for this method.
	 */
	public abstract String getGrammarFileName();

	/**
	 * Get the {@link ATN} used by the recognizer for prediction.
	 *
	 * @return The {@link ATN} used by the recognizer for prediction.
	 */
	public abstract ATN getATN();

	/**
	 * Get the ATN interpreter used by the recognizer for prediction.
	 *
	 * @return The ATN interpreter used by the recognizer for prediction.

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Call getSerializedATN() only on generated recognizer classes, which override it
  2. If you built the interpreter yourself, keep the original serialized ATN string alongside it instead of re-asking the recognizer
  3. Guard with an instanceof/generated check before calling (see validation below)

Example fix

// before
String atn = recognizer.getSerializedATN(); // throws for interpreters

// after
String atn = (recognizer instanceof ParserInterpreter)
    ? savedSerializedAtn   // you kept it when constructing the interpreter
    : recognizer.getSerializedATN();
Defensive patterns

Strategy: validation

Validate before calling

boolean isGenerated = recognizer.getClass().getPackage() != null
    && recognizer.getGrammarFileName().endsWith(".g4");
// simplest reliable check: generated classes override getSerializedATN without throwing
if (!(recognizer instanceof LexerInterpreter || recognizer instanceof ParserInterpreter)) {
    String atn = recognizer.getSerializedATN(); // safe for generated classes
}

Type guard

static boolean canSupplySerializedAtn(Recognizer<?, ?> r) {
    return !(r instanceof LexerInterpreter) && !(r instanceof ParserInterpreter);
}

Prevention

When it happens

Trigger: Calling recognizer.getSerializedATN() on a Recognizer, LexerInterpreter, or ParserInterpreter instance (the method is only overridden in generated Lexer/Parser subclasses); serialization or tooling code that reflects over arbitrary recognizers.

Common situations: Grammar-inspection utilities, cache keys built from the ATN string, or porting generated-code assumptions to interpreter-based parsing of arbitrary grammars at runtime.

Related errors


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