antlr/antlr4 · error · ArgumentException

invalid tag: {tag} in pattern: {pattern}

Error message

invalid tag: {tag} in pattern: {pattern}

What it means

While compiling a pattern, a tag's first character is neither uppercase (token tag) nor lowercase (rule tag) — e.g. it starts with a digit, underscore, or non-ASCII character. The matcher's convention is: uppercase first letter = token reference, lowercase first letter = rule reference; anything else cannot be classified and is rejected.

Source

Thrown at runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs:559

                        }
                        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)
                    {
                        tokens.Add(t);
                        t = lexer.NextToken();
                    }
                }
            }
            //		System.out.println("tokens="+tokens);
            return tokens;

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Rename the tag so its first letter is uppercase (token) or lowercase (rule) per ANTLR's convention.
  2. Use labels for arbitrary names: <name:expr> — the label part is unrestricted, only the tag itself must start with a letter.
  3. Sanitize programmatically generated tags: ensure the first char is an ASCII letter before embedding them in a pattern.

Example fix

// before
var p = parser.CompileParseTreePattern("<_id> = <expr>", ExprParser.RULE_assign, null);

// after
var p = parser.CompileParseTreePattern("<val:_id> = <expr>", ExprParser.RULE_assign, null); // or rename tag to 'id'
Defensive patterns

Strategy: validation

Validate before calling

static bool IsValidTagFirstChar(char c) => char.IsUpper(c) || char.IsLower(c);
// sanitize generated tags
string tag = char.IsLetter(raw[0]) ? raw : "x" + raw;

Type guard

static bool IsValidTag(string tag) => tag.Length > 0 && (char.IsUpper(tag[0]) || char.IsLower(tag[0]));

Prevention

When it happens

Trigger: A pattern containing a tag like <_id>, <2nd>, <Ünicode>, or <'quoted'> passed to CompileParseTreePattern or ParseTreePatternMatcher.Compile.

Common situations: Programmatically building pattern strings and interpolating user input that starts with a digit; using snake_case tag names (common in C# conventions) inside patterns; localized grammars with non-ASCII identifiers.

Related errors


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