{"record":{"id":"39079e7a8d314bea","repo":"antlr/antlr4","slug":"invalid-tag-tag-in-pattern-pattern","errorCode":null,"errorMessage":"invalid tag: {tag} in pattern: {pattern}","messagePattern":"invalid tag: (.+?) in pattern: (.+?)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs","lineNumber":559,"sourceCode":"                        }\n                        TokenTagToken t = new TokenTagToken(tagChunk.Tag, ttype, tagChunk.Label);\n                        tokens.Add(t);\n                    }\n                    else\n                    {\n                        if (System.Char.IsLower(tagChunk.Tag[0]))\n                        {\n                            int ruleIndex = parser.GetRuleIndex(tagChunk.Tag);\n                            if (ruleIndex == -1)\n                            {\n                                throw new ArgumentException(\"Unknown rule \" + tagChunk.Tag + \" in pattern: \" + pattern);\n                            }\n                            int ruleImaginaryTokenType = parser.GetATNWithBypassAlts().ruleToTokenType[ruleIndex];\n                            tokens.Add(new RuleTagToken(tagChunk.Tag, ruleImaginaryTokenType, tagChunk.Label));\n                        }\n                        else\n                        {\n                            throw new ArgumentException(\"invalid tag: \" + tagChunk.Tag + \" in pattern: \" + pattern);\n                        }\n                    }\n                }\n                else\n                {\n                    TextChunk textChunk = (TextChunk)chunk;\n                    AntlrInputStream @in = new AntlrInputStream(textChunk.Text);\n                    lexer.SetInputStream(@in);\n                    IToken t = lexer.NextToken();\n                    while (t.Type != TokenConstants.EOF)\n                    {\n                        tokens.Add(t);\n                        t = lexer.NextToken();\n                    }\n                }\n            }\n            //\t\tSystem.out.println(\"tokens=\"+tokens);\n            return tokens;","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs#L541-L577","documentation":"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.","triggerScenarios":"A pattern containing a tag like <_id>, <2nd>, <Ünicode>, or <'quoted'> passed to CompileParseTreePattern or ParseTreePatternMatcher.Compile.","commonSituations":"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.","solutions":["Rename the tag so its first letter is uppercase (token) or lowercase (rule) per ANTLR's convention.","Use labels for arbitrary names: <name:expr> — the label part is unrestricted, only the tag itself must start with a letter.","Sanitize programmatically generated tags: ensure the first char is an ASCII letter before embedding them in a pattern."],"exampleFix":"// before\nvar p = parser.CompileParseTreePattern(\"<_id> = <expr>\", ExprParser.RULE_assign, null);\n\n// after\nvar p = parser.CompileParseTreePattern(\"<val:_id> = <expr>\", ExprParser.RULE_assign, null); // or rename tag to 'id'","handlingStrategy":"validation","validationCode":"static bool IsValidTagFirstChar(char c) => char.IsUpper(c) || char.IsLower(c);\n// sanitize generated tags\nstring tag = char.IsLetter(raw[0]) ? raw : \"x\" + raw;","typeGuard":"static bool IsValidTag(string tag) => tag.Length > 0 && (char.IsUpper(tag[0]) || char.IsLower(tag[0]));","tryCatchPattern":null,"preventionTips":["Remember the convention: uppercase-first = token tag, lowercase-first = rule tag; anything else is invalid.","Use labels (<label:tag>) for arbitrary names; sanitize programmatically generated tags."],"tags":["antlr","csharp","pattern","tag","naming-convention"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}