{"record":{"id":"ea8eba24129cb49d","repo":"antlr/antlr4","slug":"start-cannot-be-null-or-empty-ea8eba","errorCode":null,"errorMessage":"start cannot be null or empty","messagePattern":"start cannot be null or empty","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs","lineNumber":218,"sourceCode":"        /// if\n        /// <paramref name=\"start\"/>\n        /// is\n        /// <see langword=\"null\"/>\n        /// or empty.\n        /// </exception>\n        /// <exception>\n        /// IllegalArgumentException\n        /// if\n        /// <paramref name=\"stop\"/>\n        /// is\n        /// <see langword=\"null\"/>\n        /// or empty.\n        /// </exception>\n        public virtual void SetDelimiters(string start, string stop, string escapeLeft)\n        {\n            if (string.IsNullOrEmpty(start))\n            {\n                throw new ArgumentException(\"start cannot be null or empty\");\n            }\n            if (string.IsNullOrEmpty(stop))\n            {\n                throw new ArgumentException(\"stop cannot be null or empty\");\n            }\n            this.start = start;\n            this.stop = stop;\n            this.escape = escapeLeft;\n        }\n\n        /// <summary>\n        /// Does\n        /// <paramref name=\"pattern\"/>\n        /// matched as rule\n        /// <paramref name=\"patternRuleIndex\"/>\n        /// match\n        /// <paramref name=\"tree\"/>\n        /// ?","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/CSharp/src/Tree/Pattern/ParseTreePatternMatcher.cs#L200-L236","documentation":"ParseTreePatternMatcher.SetDelimiters rejects a null or empty start delimiter. The delimiters define how tags are recognized inside pattern strings (default '<' and '>'); an empty start delimiter would make tag scanning ambiguous or infinite, so it is rejected with ArgumentException.","triggerScenarios":"Calling matcher.SetDelimiters(\"\", \"]\", \"\\\\\") or SetDelimiters(null, ...) — typically when a configurable delimiter string comes from config and is missing.","commonSituations":"Making delimiters configurable via appsettings/environment and the key is absent; copying example code that passes an empty string as a placeholder; switching delimiter style (e.g. to '[' / ']') but forgetting to supply both values.","solutions":["Supply a non-empty start delimiter string, e.g. SetDelimiters(\"[\", \"]\", \"\\\\\").","Validate configuration before calling SetDelimiters: fail with a clear config error naming the missing key.","Do not call SetDelimiters at all if you want the default '<' and '>' delimiters."],"exampleFix":"// before\nmatcher.SetDelimiters(cfg[\"tagStart\"], cfg[\"tagStop\"], \"\\\\\"); // tagStart missing -> null\n\n// after\nstring start = cfg[\"tagStart\"];\nif (string.IsNullOrEmpty(start)) throw new ConfigException(\"tagStart not set\");\nmatcher.SetDelimiters(start, cfg[\"tagStop\"], \"\\\\\");","handlingStrategy":"validation","validationCode":"if (string.IsNullOrEmpty(start)) throw new ConfigurationErrorsException(\"pattern tag start delimiter is missing\");\nmatcher.SetDelimiters(start, stop, escape);","typeGuard":"static bool IsValidDelimiter(string s) => !string.IsNullOrEmpty(s);","tryCatchPattern":null,"preventionTips":["Validate delimiter config keys before calling SetDelimiters.","Skip the call entirely to keep the default '<' and '>' delimiters."],"tags":["antlr","csharp","pattern-matcher","delimiters","validation"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}