{"record":{"id":"6d64e47e458453a8","repo":"oraios/serena","slug":"invalid-glob-brace-expression-in-pattern-r-empt","errorCode":null,"errorMessage":"Invalid glob brace expression in {pattern!r}: empty braces are not allowed","messagePattern":"Invalid glob brace expression in (.+?): empty braces are not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/serena/util/text_utils.py","lineNumber":229,"sourceCode":"    def _tostring_includes(self) -> list[str]:\n        return [\"_glob_expr\"]\n\n    @staticmethod\n    def _expand_braces(pattern: str) -> list[str]:\n        \"\"\"\n        Expands brace patterns in a glob string.\n        For example, \"**/*.{js,jsx,ts,tsx}\" becomes [\"**/*.js\", \"**/*.jsx\", \"**/*.ts\", \"**/*.tsx\"].\n        Handles multiple brace sets as well.\n        \"\"\"\n        patterns = [pattern]\n        while any(\"{\" in p or \"}\" in p for p in patterns):\n            new_patterns = []\n            for p in patterns:\n                match = re.search(r\"\\{([^{}]*)\\}\", p)\n                if match:\n                    options_expr = match.group(1)\n                    if not options_expr:\n                        raise ValueError(f\"Invalid glob brace expression in {pattern!r}: empty braces are not allowed\")\n\n                    prefix = p[: match.start()]\n                    suffix = p[match.end() :]\n                    options = options_expr.split(\",\")\n                    for option in options:\n                        new_patterns.append(f\"{prefix}{option}{suffix}\")\n                else:\n                    raise ValueError(f\"Invalid glob brace expression in {pattern!r}: unmatched brace\")\n            patterns = new_patterns\n        return patterns\n\n    @staticmethod\n    def _translate_glob_to_regex(pattern: str) -> str:\n        res = []\n        i = 0\n        n = len(pattern)\n        while i < n:\n            c = pattern[i]","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/serena/util/text_utils.py#L211-L247","documentation":"TextUtils._expand_braces expands glob brace expressions like src/*.{py,txt}. When the innermost {...} group matched by the regex is empty ({}), it raises ValueError because empty braces are a malformed brace expression, referencing the original pattern.","triggerScenarios":"Passing a glob pattern containing '{}' (empty braces) to any API that constructs a GlobPattern/_expand_braces — e.g. search_for_text_overflow patterns or path filters with a typo like 'src/**/{}/*.py'.","commonSituations":"Editor variables left unexpanded (template placeholders like {} not substituted); copy-pasted glob patterns with dangling braces; f-string formatting mistakes producing {}.","solutions":["Remove the empty braces or replace with a valid alternation like {a,b}","If you meant a literal brace, escape it appropriately or use a pattern without braces","Validate/interpolate template placeholders before building the glob","Catch ValueError and report the offending pattern to the user"],"exampleFix":"// before\npattern = 'src/**/{}/*.py'\n// after\npattern = 'src/**/*.py'  # or 'src/**/{a,b}/*.py'","handlingStrategy":"validation","validationCode":"def has_empty_braces(pattern: str) -> bool:\n    return \"{}\" in pattern\nif has_empty_braces(glob):\n    raise ValueError(\"glob contains empty braces {}\")","typeGuard":null,"tryCatchPattern":"try:\n    results = TextUtils.search_text(pat, source_file_path=f)\nexcept ValueError as e:\n    if \"empty braces\" in str(e):\n        pat = pat.replace(\"{}\", \"\")\n    else:\n        raise","preventionTips":["Interpolate template placeholders before building glob patterns","Lint user-supplied globs for empty or unbalanced braces","Prefer plain wildcards over brace expansion when alternation isn't needed"],"tags":["python","glob","valueerror","pattern-validation"],"backgroundTag":"invalid-glob-pattern","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}