oraios/serena · error · ValueError

occurrence_ids is empty - pass at least one id from a dry ru

Error message

occurrence_ids is empty - pass at least one id from a dry run, or omit the parameter to replace all.

What it means

When occurrence_ids is given but resolves to an empty selection, apply() raises this ValueError instead of silently replacing nothing or everything. It guards against the ambiguous case of an empty id list, since omitting the parameter means 'replace all'.

Source

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

        replacer = MultiFileContentReplacer(mode=mode)
        files = self._collect_files(relative_path, paths_include_glob, paths_exclude_glob)
        occurrences = replacer.find_occurrences(files, needle, repl)
        contents = dict(files)

        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]

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Pass at least one valid occurrence id from a prior dry run
  2. Omit occurrence_ids to replace all occurrences
  3. Check the dry-run result for matches before constructing the id list; abort or adjust the pattern if none
  4. Fix code that defaults occurrence_ids to [] instead of None

Example fix

// before
ids = [o.id for o in dry.occurrences]  # may be []
agent.replace_content(needle="foo", repl="bar", occurrence_ids=ids)
// after
ids = [o.id for o in dry.occurrences]
agent.replace_content(needle="foo", repl="bar", occurrence_ids=ids or None)
Defensive patterns

Strategy: validation

Validate before calling

dry = agent.replace_content(needle, repl, dry_run=True)
ids = [o.id for o in dry.occurrences]
if not ids:
    return  # nothing to replace; skip apply
agent.replace_content(needle, repl, occurrence_ids=ids)

Type guard

def has_selection(ids) -> bool:
    return ids is not None and len(ids) > 0

Try / catch

try:
    agent.replace_content(needle, repl, occurrence_ids=ids)
except ValueError as e:
    if "occurrence_ids is empty" in str(e):
        agent.replace_content(needle, repl)  # or abort
    else:
        raise

Prevention

When it happens

Trigger: Calling replace_content with occurrence_ids=[] (empty list); passing ids that were all filtered out by an empty pattern match; programmatically building the id list from an empty dry-run result.

Common situations: Code that collects ids conditionally and ends up with an empty list; template-based agents that always serialize the parameter even when no ids were selected.

Related errors


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