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
- Call getSerializedATN() only on generated recognizer classes, which override it
- If you built the interpreter yourself, keep the original serialized ATN string alongside it instead of re-asking the recognizer
- 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
- Keep the serialized ATN string you used to build an interpreter
- Only call getSerializedATN() on generated classes
- Abstract ATN access behind your own interface that knows the provenance
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
- 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.
- Serialized ATN data element[i] = v doesn't fit in 31 bits
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/f578d3d24ba3216a.
Report an issue: GitHub.