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
- Pass at least one valid occurrence id from a prior dry run
- Omit occurrence_ids to replace all occurrences
- Check the dry-run result for matches before constructing the id list; abort or adjust the pattern if none
- 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
- Pass None (not []) when the parameter is intentionally unused
- Check dry-run match count before constructing id lists
- Avoid unconditional serialization of optional list params
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
- {len(problems)} of the given occurrence_ids could not be res
- 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/0be99a16f9c0b341.
Report an issue: GitHub.