{"record":{"id":"530197f6cf555c74","repo":"oraios/serena","slug":"invalid-mode-mode-expected-literal-or-reg","errorCode":null,"errorMessage":"Invalid mode: '{mode}', expected 'literal' or 'regex'.","messagePattern":"Invalid mode: '(.+?)', expected 'literal' or 'regex'\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/serena/util/text_utils.py","lineNumber":524,"sourceCode":"\nclass MultiFileContentReplacer:\n    \"\"\"\n    Occurrence-level counterpart of :class:`ContentReplacer` operating on multiple files:\n    finds every match of a pattern across a set of file contents, assigns each occurrence a\n    stable content-anchored id, renders minimal line diffs for previewing, and computes the\n    updated content of a file for a selected subset of occurrences.\n    \"\"\"\n\n    OCCURRENCE_ID_REGEX = re.compile(r\"^(?P<path>.+):(?P<index>\\d+)@(?P<digest>[0-9a-f]{6})$\")\n    _DIGEST_LEN = 6\n\n    def __init__(self, mode: Literal[\"literal\", \"regex\"], regex_multiline: bool = True):\n        \"\"\"\n        :param mode: whether the needle is a literal string (\"literal\") or a regular expression (\"regex\")\n        :param regex_multiline: whether to apply multi-line regex matching, enabling the flags re.DOTALL and re.MULTILINE\n        \"\"\"\n        if mode not in (\"literal\", \"regex\"):\n            raise ValueError(f\"Invalid mode: '{mode}', expected 'literal' or 'regex'.\")\n        self.mode = mode\n        self._flags = (re.MULTILINE | re.DOTALL) if regex_multiline else 0\n\n    def _compile(self, needle: str) -> re.Pattern:\n        return re.compile(re.escape(needle) if self.mode == \"literal\" else needle, flags=self._flags)\n\n    @classmethod\n    def _digest(cls, matched_text: str) -> str:\n        return hashlib.sha1(matched_text.encode(\"utf-8\")).hexdigest()[: cls._DIGEST_LEN]\n\n    @classmethod\n    def make_occurrence_id(cls, relative_path: str, index_in_file: int, matched_text: str) -> str:\n        return f\"{relative_path}:{index_in_file}@{cls._digest(matched_text)}\"\n\n    @staticmethod\n    def _expand_backreferences(match: re.Match, repl_template: str) -> str:\n        \"\"\"Expands $!1, $!2, ... in the replacement template (same syntax as :class:`ContentReplacer`).\"\"\"\n","sourceCodeStart":506,"sourceCodeEnd":542,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/serena/util/text_utils.py#L506-L542","documentation":"Constructor-level validation in RegExpEditMode: the mode parameter must be the exact string 'literal' or 'regex'. Anything else is rejected before any matching happens, mirroring error 151 but at construction time.","triggerScenarios":"Instantiating RegExpEditMode with mode values like 'Literal', 'raw', '', None, or values read from unvalidated config/user input.","commonSituations":"Deserialized settings where mode came from JSON/YAML without an enum check; typos when hand-writing editor tooling; language bindings passing wrong types.","solutions":["Pass exactly 'literal' or 'regex'","Normalize input with .strip().lower() before constructing","Use typing Literal['literal','regex'] and a static type checker to catch it at authoring time"],"exampleFix":"// before\nRegExpEditMode(mode='REGEX')\n// after\nmode = 'REGEX'.strip().lower()  # 'regex'\nRegExpEditMode(mode=mode)  # ok: 'literal' or 'regex'","handlingStrategy":"validation","validationCode":"assert mode in ('literal', 'regex'), f'bad mode: {mode!r}'","typeGuard":"def valid_mode(m: object) -> TypeGuard[Literal['literal','regex']]:\n    return isinstance(m, str) and m in ('literal', 'regex')","tryCatchPattern":"try:\n    edit_mode = RegExpEditMode(mode)\nexcept ValueError as e:\n    if 'Invalid mode' in str(e):\n        edit_mode = RegExpEditMode('literal')\n    else:\n        raise","preventionTips":["Validate config-driven mode strings at load time","Use Literal typing plus mypy","Keep mode constants in one shared location"],"tags":["regex","validation","invalid-argument"],"backgroundTag":"invalid-enum-value","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}