oraios/serena · error

Expression matches occurrences. Please revise the…

Error message

Expression matches {n} occurrences. Please revise the expression to be more specific or enable allow_multiple_occurrences if this is expected.

What it means

replace() expects the expression to match exactly once unless allow_multiple_occurrences is set. When re.subn reports n > 1 matches, the library refuses to replace all of them blindly and asks you to make the expression more specific or opt in explicitly.

Solutions

  1. Add surrounding unique context to the needle so it matches only the intended occurrence
  2. Set allow_multiple_occurrences=True if replacing all occurrences is intended
  3. Use an index/offset-based replacement or loop with per-occurrence context
  4. Include a larger anchor span (function signature, section header) in the pattern

Example fix

// before
replacer.replace(content, 'timeout=30', 'timeout=60')  # appears 3 times
// after
replacer.replace(content, r'(client_config:.*?timeout=)30', r'\g<1>60')  # scoped, unique
# or: TextReplacement(..., allow_multiple_occurrences=True)
Defensive patterns

Strategy: validation

Validate before calling

n = len(re.findall(regex, content, flags=re.MULTILINE|re.DOTALL))
if n > 1 and not allow_multiple:
    raise ValueError(f'{n} matches; narrow the pattern or set allow_multiple_occurrences')

Try / catch

try:
    updated = editor.replace(content, needle, repl)
except ValueError as e:
    if 'matches' in str(e) and 'occurrences' in str(e):
        editor.allow_multiple_occurrences = True
        updated = editor.replace(content, needle, repl)
    else:
        raise

Prevention

When it happens

Trigger: Calling replace() with a pattern matching 2+ places in content while allow_multiple_occurrences=False (the default), e.g. a generic needle like 'version = ...' repeated in several sections.

Common situations: Editing boilerplate that appears in many files or blocks of the same file; overly broad regexes like '\\d+' or repeated comment markers; literal strings that occur in both header and body.

Related errors


AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29). Data as JSON: /api/errors/04c247793c8723ed. Report an issue: GitHub.

Appendix: source

Thrown at src/serena/util/text_utils.py:476

        if self.mode == "literal":
            regex = re.escape(needle)
        elif self.mode == "regex":
            regex = needle
        else:
            raise ValueError(f"Invalid mode: '{self.mode}', expected 'literal' or 'regex'.")

        regex_flags = (re.MULTILINE | re.DOTALL) if self.regex_multiline else 0

        # create replacement function with validation and backreference handling
        repl_fn = self._create_replacement_function(regex, repl, regex_flags=regex_flags)

        # perform replacement
        updated_content, n = re.subn(regex, repl_fn, content, flags=regex_flags)

        if n == 0:
            raise ValueError("Error: No matches of search expression found.")
        if not self.allow_multiple_occurrences and n > 1:
            raise ValueError(
                f"Expression matches {n} occurrences. "
                "Please revise the expression to be more specific or enable allow_multiple_occurrences if this is expected."
            )
        return updated_content


@dataclass
class ReplacementOccurrence:
    """A single prospective replacement of a pattern match within one file."""

    occurrence_id: str
    """stable, content-anchored identifier: '<relative_path>:<index_in_file>@<digest>'"""
    relative_path: str
    index_in_file: int
    """0-based index of this match among the matches within its file (in position order)"""
    start: int
    """character offset of the match start within the file content"""
    end: int

View on GitHub (pinned to 7fcbca7e62)