{"record":{"id":"ab8167f9de51fc30","repo":"antlr/antlr4","slug":"start-cannot-be-null-or-empty-ab8167","errorCode":null,"errorMessage":"start cannot be null or empty","messagePattern":"start cannot be null or empty","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"runtime/Python3/src/antlr4/tree/ParseTreePatternMatcher.py","lineNumber":117,"sourceCode":"        self.lexer = lexer\n        self.parser = parser\n        self.start = \"<\"\n        self.stop = \">\"\n        self.escape = \"\\\\\"  # e.g., \\< and \\> must escape BOTH!\n\n    # Set the delimiters used for marking rule and token tags within concrete\n    # syntax used by the tree pattern parser.\n    #\n    # @param start The start delimiter.\n    # @param stop The stop delimiter.\n    # @param escapeLeft The escape sequence to use for escaping a start or stop delimiter.\n    #\n    # @exception IllegalArgumentException if {@code start} is {@code null} or empty.\n    # @exception IllegalArgumentException if {@code stop} is {@code null} or empty.\n    #\n    def setDelimiters(self, start:str, stop:str, escapeLeft:str):\n        if start is None or len(start)==0:\n            raise Exception(\"start cannot be null or empty\")\n        if stop is None or len(stop)==0:\n            raise Exception(\"stop cannot be null or empty\")\n        self.start = start\n        self.stop = stop\n        self.escape = escapeLeft\n\n    # Does {@code pattern} matched as rule {@code patternRuleIndex} match {@code tree}?#\n    def matchesRuleIndex(self, tree:ParseTree, pattern:str, patternRuleIndex:int):\n        p = self.compileTreePattern(pattern, patternRuleIndex)\n        return self.matches(tree, p)\n\n    # Does {@code pattern} matched as rule patternRuleIndex match tree? Pass in a\n    #  compiled pattern instead of a string representation of a tree pattern.\n    #\n    def matchesPattern(self, tree:ParseTree, pattern:ParseTreePattern):\n        mismatchedNode = self.matchImpl(tree, pattern.patternTree, dict())\n        return mismatchedNode is None\n","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Python3/src/antlr4/tree/ParseTreePatternMatcher.py#L99-L135","documentation":"Thrown by ParseTreePatternMatcher.setDelimiters() in the Python3 runtime when the start delimiter is None or the empty string. The delimiters (default '<' and '>') mark token/rule tags like <ID> inside a tree pattern string, so an empty start delimiter makes tag splitting impossible. The API contract explicitly forbids null or empty delimiters.","triggerScenarios":"Calling matcher.setDelimiters('', '>', '\\\\') or setDelimiters(None, ...) to try to change tag syntax before compiling a pattern.","commonSituations":"Switching delimiters to allow literal '<' in matched text, or copying a delimiter string from config that arrived empty because of a typo or missing env var.","solutions":["Pass a non-empty string for start, e.g. setDelimiters('<<', '>>', '\\\\')","Check delimiter values are non-empty before calling setDelimiters","If you meant to match a literal '<' character, escape it with the escape delimiter instead of clearing the delimiters"],"exampleFix":"# before\nmatcher.setDelimiters('', '>', '\\\\')\n\n# after\nmatcher.setDelimiters('<<', '>>', '\\\\')  # non-empty start and stop","handlingStrategy":"validation","validationCode":"if not start:\n    raise ValueError('start delimiter must be a non-empty string')\nmatcher.setDelimiters(start, stop, escape)","typeGuard":"def is_non_empty_str(s) -> bool:\n    return isinstance(s, str) and len(s) > 0","tryCatchPattern":null,"preventionTips":["Validate delimiter config before calling setDelimiters","Keep delimiters in one config object tested at startup"],"tags":["antlr","python","parse-tree-matching","validation"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}