{"record":{"id":"4dd5fc5bacf43807","repo":"antlr/antlr4","slug":"missing-start-tag-in-pattern-pattern-4dd5fc","errorCode":null,"errorMessage":"missing start tag in pattern: {pattern}","messagePattern":"missing start tag in pattern: (.+?)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs","lineNumber":638,"sourceCode":"                            }\n                            else\n                            {\n                                p++;\n                            }\n                        }\n                    }\n                }\n            }\n            //\t\tSystem.out.println(\"\");\n            //\t\tSystem.out.println(starts);\n            //\t\tSystem.out.println(stops);\n            if (starts.Count > stops.Count)\n            {\n                throw new ArgumentException(\"unterminated tag in pattern: \" + pattern);\n            }\n            if (starts.Count < stops.Count)\n            {\n                throw new ArgumentException(\"missing start tag in pattern: \" + pattern);\n            }\n            int ntags = starts.Count;\n            for (int i = 0; i < ntags; i++)\n            {\n                if (starts[i] >= stops[i])\n                {\n                    throw new ArgumentException(\"tag delimiters out of order in pattern: \" + pattern);\n                }\n            }\n            // collect into chunks now\n            if (ntags == 0)\n            {\n                string text = Sharpen.Runtime.Substring(pattern, 0, n);\n                chunks.Add(new TextChunk(text));\n            }\n            if (ntags > 0 && starts[0] > 0)\n            {\n                // copy text up to first tag into chunks","sourceCodeStart":620,"sourceCodeEnd":656,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs#L620-L656","documentation":"While splitting a pattern, the scanner found more stop delimiters than start delimiters — a '>' (or custom stop) that appears without a preceding unmatched '<'. Like the unterminated-tag case, escaped stops (default '\\>') are not counted, so an escape-character mismatch between pattern and matcher configuration also triggers this.","triggerScenarios":"Pattern strings like \"ID> = 3\" or \"a > b\" (comparison operators as plain text) passed to Compile; switching escape characters via SetDelimiters while patterns still use the old escape.","commonSituations":"Matching source that contains '>' as text (generics like List<int>, arrow operators); unbalanced quotes/delimiters from string concatenation bugs; patterns assembled from templates that drop an opening delimiter.","solutions":["Balance the pattern: remove the stray '>' or add the missing '<'.","Escape '>' that is meant as text: \\>.","Pick delimiters that never occur in the target text via SetDelimiters.","Add a pre-compile lint for user patterns: unescaped starts must equal unescaped stops."],"exampleFix":"// before\nvar p = parser.CompileParseTreePattern(\"List<int>> items\", RULE_type, null);\n\n// after\nvar p = parser.CompileParseTreePattern(\"List\\<int\\>\\> items\", RULE_type, null); // or use labels/tags for the type","handlingStrategy":"validation","validationCode":"int CountUnescaped(string s, char c) { int n = 0; for (int i = 0; i < s.Length; i++) { if (s[i] == '\\\\') i++; else if (s[i] == c) n++; } return n; }\nif (CountUnescaped(pattern, '<') < CountUnescaped(pattern, '>')) throw new ArgumentException(\"missing start tag\");","typeGuard":null,"tryCatchPattern":"try { matcher.Compile(pattern); } catch (ArgumentException ex) when (ex.Message.Contains(\"missing start tag\")) { /* remove or escape the stray '>' */ }","preventionTips":["Escape '>' meant as text (\\>) — common when matching generics or comparisons.","Consider custom delimiters via SetDelimiters if the target text is full of angle brackets."],"tags":["antlr","csharp","pattern","delimiters","escaping"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}