{"record":{"id":"5fdefda21c27fcf4","repo":"antlr/antlr4","slug":"stop-cannot-be-null-or-empty-5fdefd","errorCode":null,"errorMessage":"stop cannot be null or empty","messagePattern":"stop cannot be null or empty","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"runtime/Python3/src/antlr4/tree/ParseTreePatternMatcher.py","lineNumber":119,"sourceCode":"        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\n    #\n    # Compare {@code pattern} matched as rule {@code patternRuleIndex} against","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Python3/src/antlr4/tree/ParseTreePatternMatcher.py#L101-L137","documentation":"Thrown by ParseTreePatternMatcher.setDelimiters() in the Python3 runtime when the stop delimiter is None or the empty string. The stop delimiter closes tags like <ID>, so an empty one leaves tags unterminated and the split() step cannot work. The API contract explicitly forbids null or empty delimiters.","triggerScenarios":"Calling matcher.setDelimiters('<', '', '\\\\') or passing None as the second argument.","commonSituations":"Symmetric attempt to reconfigure delimiters with a partially filled config, or a copy/paste that only set the start delimiter.","solutions":["Pass a non-empty stop string, e.g. setDelimiters('<<', '>>', '\\\\')","Validate both delimiters are non-empty before calling setDelimiters","Keep start and stop distinct so split() can pair them correctly"],"exampleFix":"# before\nmatcher.setDelimiters('<<', '', '\\\\')\n\n# after\nmatcher.setDelimiters('<<', '>>', '\\\\')","handlingStrategy":"validation","validationCode":"if not stop:\n    raise ValueError('stop 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 both delimiters together","Add a unit test asserting setDelimiters works with your config"],"tags":["antlr","python","parse-tree-matching","validation"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}