antlr/antlr4 · error · ArgumentException
Unknown rule {tag} in pattern: {pattern}
Error message
Unknown rule {tag} in pattern: {pattern} What it means
While compiling a pattern, a tag starting with a lowercase letter (rule tag, e.g. <expr>) does not resolve to any rule index in the parser (GetRuleIndex returned -1). Rule tags must name a parser rule declared in the grammar the parser was generated from; unknown names indicate a typo or a grammar/parser version mismatch.
Source
Thrown at runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs:552
// add special rule token or conjure up new token from name
if (System.Char.IsUpper(tagChunk.Tag[0]))
{
int ttype = parser.GetTokenType(tagChunk.Tag);
if (ttype == TokenConstants.InvalidType)
{
throw new ArgumentException("Unknown token " + tagChunk.Tag + " in pattern: " + pattern);
}
TokenTagToken t = new TokenTagToken(tagChunk.Tag, ttype, tagChunk.Label);
tokens.Add(t);
}
else
{
if (System.Char.IsLower(tagChunk.Tag[0]))
{
int ruleIndex = parser.GetRuleIndex(tagChunk.Tag);
if (ruleIndex == -1)
{
throw new ArgumentException("Unknown rule " + tagChunk.Tag + " in pattern: " + pattern);
}
int ruleImaginaryTokenType = parser.GetATNWithBypassAlts().ruleToTokenType[ruleIndex];
tokens.Add(new RuleTagToken(tagChunk.Tag, ruleImaginaryTokenType, tagChunk.Label));
}
else
{
throw new ArgumentException("invalid tag: " + tagChunk.Tag + " in pattern: " + pattern);
}
}
}
else
{
TextChunk textChunk = (TextChunk)chunk;
AntlrInputStream @in = new AntlrInputStream(textChunk.Text);
lexer.SetInputStream(@in);
IToken t = lexer.NextToken();
while (t.Type != TokenConstants.EOF)
{View on GitHub (pinned to 7d5770395b)
Solutions
- Rename the tag to the exact rule name from the grammar (check parser.RuleNames or the generated parser class).
- If the tag names a token, capitalize its first letter so it is treated as a token tag.
- Regenerate the parser after grammar edits and update pattern strings together; add a startup check that compiles all patterns to fail fast.
- Wrap CompileParseTreePattern in try/catch ArgumentException to log which pattern failed when patterns come from external config.
Example fix
// before
var p = parser.CompileParseTreePattern("<ID> = <expression>", ExprParser.RULE_assign, null);
// after (rule is 'expr' in the grammar)
var p = parser.CompileParseTreePattern("<ID> = <expr>", ExprParser.RULE_assign, null); Defensive patterns
Strategy: validation
Validate before calling
foreach (var tag in ExtractRuleTags(pattern))
if (parser.GetRuleIndex(tag) == -1)
throw new ArgumentException($"pattern references unknown rule <{tag}>");
var p = parser.CompileParseTreePattern(pattern, ruleIndex, null); Try / catch
try { var p = parser.CompileParseTreePattern(pattern, ruleIndex, null); } catch (ArgumentException ex) when (ex.Message.StartsWith("Unknown rule")) { /* report pattern and parser.RuleNames */ } Prevention
- Regenerate the parser after grammar edits and update rule references in patterns together.
- Compile all patterns once at startup to fail fast with a clear message.
When it happens
Trigger: CompileParseTreePattern("<ID> = <expression>", ...) when the rule is called expr; using a pattern authored for a different grammar; rule renamed during refactoring without regenerating or updating patterns.
Common situations: Patterns stored as string constants drift after grammar refactors; multi-version tooling where the same pattern is run against parsers from several grammar versions; documentation examples copied into a project with different rule names.
Related errors
- Unknown token {tag} in pattern: {pattern}
- pattern cannot be null
- invalid tag: {tag} in pattern: {pattern}
- unterminated tag in pattern: {pattern}
- missing start tag in pattern: {pattern}
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/31abaf428a7a8b12.
Report an issue: GitHub.