oraios/serena · error
Invalid mode: '{mode}', expected 'literal' or 'regex'.
Error message
Invalid mode: '{mode}', expected 'literal' or 'regex'. What it means
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.
Source
Thrown at src/serena/util/text_utils.py:524
class MultiFileContentReplacer:
"""
Occurrence-level counterpart of :class:`ContentReplacer` operating on multiple files:
finds every match of a pattern across a set of file contents, assigns each occurrence a
stable content-anchored id, renders minimal line diffs for previewing, and computes the
updated content of a file for a selected subset of occurrences.
"""
OCCURRENCE_ID_REGEX = re.compile(r"^(?P<path>.+):(?P<index>\d+)@(?P<digest>[0-9a-f]{6})$")
_DIGEST_LEN = 6
def __init__(self, mode: Literal["literal", "regex"], regex_multiline: bool = True):
"""
:param mode: whether the needle is a literal string ("literal") or a regular expression ("regex")
:param regex_multiline: whether to apply multi-line regex matching, enabling the flags re.DOTALL and re.MULTILINE
"""
if mode not in ("literal", "regex"):
raise ValueError(f"Invalid mode: '{mode}', expected 'literal' or 'regex'.")
self.mode = mode
self._flags = (re.MULTILINE | re.DOTALL) if regex_multiline else 0
def _compile(self, needle: str) -> re.Pattern:
return re.compile(re.escape(needle) if self.mode == "literal" else needle, flags=self._flags)
@classmethod
def _digest(cls, matched_text: str) -> str:
return hashlib.sha1(matched_text.encode("utf-8")).hexdigest()[: cls._DIGEST_LEN]
@classmethod
def make_occurrence_id(cls, relative_path: str, index_in_file: int, matched_text: str) -> str:
return f"{relative_path}:{index_in_file}@{cls._digest(matched_text)}"
@staticmethod
def _expand_backreferences(match: re.Match, repl_template: str) -> str:
"""Expands $!1, $!2, ... in the replacement template (same syntax as :class:`ContentReplacer`)."""
View on GitHub (pinned to 7fcbca7e62)
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
Example fix
// before RegExpEditMode(mode='REGEX') // after mode = 'REGEX'.strip().lower() # 'regex' RegExpEditMode(mode=mode) # ok: 'literal' or 'regex'
Defensive patterns
Strategy: validation
Validate before calling
assert mode in ('literal', 'regex'), f'bad mode: {mode!r}' Type guard
def valid_mode(m: object) -> TypeGuard[Literal['literal','regex']]:
return isinstance(m, str) and m in ('literal', 'regex') Try / catch
try:
edit_mode = RegExpEditMode(mode)
except ValueError as e:
if 'Invalid mode' in str(e):
edit_mode = RegExpEditMode('literal')
else:
raise Prevention
- Validate config-driven mode strings at load time
- Use Literal typing plus mypy
- Keep mode constants in one shared location
When it happens
Trigger: Instantiating RegExpEditMode with mode values like 'Literal', 'raw', '', None, or values read from unvalidated config/user input.
Common situations: Deserialized settings where mode came from JSON/YAML without an enum check; typos when hand-writing editor tooling; language bindings passing wrong types.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid mode: '{self.mode}', expected 'literal' or 'regex'.
- Unknown language '{lang}'. Supported: {all_langs}
- Cannot edit external file: {relative_path}
- Cannot insert after this symbol (not a function, class or me
- Cannot use both fixed_tools and excluded_tools/included_opti
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/530197f6cf555c74.
Report an issue: GitHub.