oraios/serena · error · ValueError

No occurrences of the pattern were found - NO changes were a

Error message

No occurrences of the pattern were found - NO changes were applied. Check the mode (a literal needle containing regex metacharacters must use mode 'literal'; wildcards require mode 'regex') and the path/glob restrictions, or locate the content with search_for_pattern first.

What it means

In blind-apply mode (no occurrence_ids), if the pattern matched zero occurrences, apply() raises this ValueError so no silent no-op occurs. The message points at the two most common root causes: wrong matching mode (literal vs regex) and overly restrictive path/glob scoping.

Source

Thrown at src/serena/tools/file_tools.py:297

        if dry_run:
            return self._render_listing(replacer, occurrences, contents, max_answer_chars, dry_run=True)

        if occurrence_ids is not None:
            selected, problems = self._resolve_occurrence_ids(occurrence_ids, occurrences)
            if problems:
                problem_lines = "\n".join(f"  {p}" for p in problems)
                raise ValueError(
                    f"{len(problems)} of the given occurrence_ids could not be resolved - NO changes were applied:\n"
                    f"{problem_lines}\n"
                    "Re-run with dry_run=True to obtain current occurrence ids."
                )
            if not selected:
                raise ValueError("occurrence_ids is empty - pass at least one id from a dry run, or omit the parameter to replace all.")
            return self._apply_occurrences(replacer, selected, contents, needle, repl)

        # blind apply (no ids)
        if not occurrences:
            raise ValueError(
                "No occurrences of the pattern were found - NO changes were applied. "
                "Check the mode (a literal needle containing regex metacharacters must use mode 'literal'; "
                "wildcards require mode 'regex') and the path/glob restrictions, "
                "or locate the content with search_for_pattern first."
            )
        if expected_count >= 0 and len(occurrences) != expected_count:
            listing = self._render_listing(replacer, occurrences, contents, max_answer_chars, dry_run=False)
            raise ValueError(
                f"expected_count={expected_count}, but the pattern matches {len(occurrences)} occurrence(s) - "
                f"NO changes were applied. Review the prospective changes below; re-issue with the corrected "
                f"expectation, a refined pattern, or occurrence_ids selecting the intended subset.\n{listing}"
            )
        ambiguous = [o for o in occurrences if o.is_ambiguous]
        if ambiguous:
            listing = self._render_listing(replacer, occurrences, contents, max_answer_chars, dry_run=False)
            raise ValueError(
                f"{len(ambiguous)} occurrence(s) are ambiguous (the pattern matches again inside the matched text, "
                f"indicating possible over-matching) - NO changes were applied. Review the prospective changes below "

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Set mode='literal' if the needle contains regex metacharacters and should match verbatim
  2. Switch to mode='regex' (and escape as needed) when using wildcards like foo.*bar
  3. Run search_for_pattern first to confirm the text exists and under which paths
  4. Check the path/glob parameters are not excluding the target files

Example fix

// before
agent.replace_content(needle="price(1)", repl="price(2)")
// after
agent.replace_content(needle="price(1)", repl="price(2)", mode="literal")
Defensive patterns

Strategy: validation

Validate before calling

found = agent.search_for_pattern(needle, path=path)
if not found:
    raise LookupError(f"pattern not found: {needle!r}")
agent.replace_content(needle, repl, mode="literal" if any(c in needle for c in "()[]{}.*+?^$|\\") else "regex")

Type guard

def needs_literal(needle: str) -> bool:
    import re
    return any(ch in needle for ch in "()[]{}.*+?^$|\\")

Try / catch

try:
    agent.replace_content(needle, repl)
except ValueError as e:
    if "No occurrences" in str(e):
        agent.replace_content(needle, repl, mode="literal")
    else:
        raise

Prevention

When it happens

Trigger: Using mode='regex' (default) with a literal needle containing regex metacharacters like (, [, ., or *; using wildcards while in literal mode; a path/glob filter excluding the file that contains the text; the text simply not existing (already replaced or typo).

Common situations: Replacing strings like "foo(1)" or "a.b" without mode='literal'; IDE/agent already applied the same replacement in a previous run; case or whitespace mismatch between needle and file content.

Related errors


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