{"record":{"id":"0be99a16f9c0b341","repo":"oraios/serena","slug":"occurrence-ids-is-empty-pass-at-least-one-id-fro","errorCode":null,"errorMessage":"occurrence_ids is empty - pass at least one id from a dry run, or omit the parameter to replace all.","messagePattern":"occurrence_ids is empty - pass at least one id from a dry run, or omit the parameter to replace all\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/serena/tools/file_tools.py","lineNumber":292,"sourceCode":"        replacer = MultiFileContentReplacer(mode=mode)\n        files = self._collect_files(relative_path, paths_include_glob, paths_exclude_glob)\n        occurrences = replacer.find_occurrences(files, needle, repl)\n        contents = dict(files)\n\n        if dry_run:\n            return self._render_listing(replacer, occurrences, contents, max_answer_chars, dry_run=True)\n\n        if occurrence_ids is not None:\n            selected, problems = self._resolve_occurrence_ids(occurrence_ids, occurrences)\n            if problems:\n                problem_lines = \"\\n\".join(f\"  {p}\" for p in problems)\n                raise ValueError(\n                    f\"{len(problems)} of the given occurrence_ids could not be resolved - NO changes were applied:\\n\"\n                    f\"{problem_lines}\\n\"\n                    \"Re-run with dry_run=True to obtain current occurrence ids.\"\n                )\n            if not selected:\n                raise ValueError(\"occurrence_ids is empty - pass at least one id from a dry run, or omit the parameter to replace all.\")\n            return self._apply_occurrences(replacer, selected, contents, needle, repl)\n\n        # blind apply (no ids)\n        if not occurrences:\n            raise ValueError(\n                \"No occurrences of the pattern were found - NO changes were applied. \"\n                \"Check the mode (a literal needle containing regex metacharacters must use mode 'literal'; \"\n                \"wildcards require mode 'regex') and the path/glob restrictions, \"\n                \"or locate the content with search_for_pattern first.\"\n            )\n        if expected_count >= 0 and len(occurrences) != expected_count:\n            listing = self._render_listing(replacer, occurrences, contents, max_answer_chars, dry_run=False)\n            raise ValueError(\n                f\"expected_count={expected_count}, but the pattern matches {len(occurrences)} occurrence(s) - \"\n                f\"NO changes were applied. Review the prospective changes below; re-issue with the corrected \"\n                f\"expectation, a refined pattern, or occurrence_ids selecting the intended subset.\\n{listing}\"\n            )\n        ambiguous = [o for o in occurrences if o.is_ambiguous]","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/serena/tools/file_tools.py#L274-L310","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nids = [o.id for o in dry.occurrences]  # may be []\nagent.replace_content(needle=\"foo\", repl=\"bar\", occurrence_ids=ids)\n// after\nids = [o.id for o in dry.occurrences]\nagent.replace_content(needle=\"foo\", repl=\"bar\", occurrence_ids=ids or None)","handlingStrategy":"validation","validationCode":"dry = agent.replace_content(needle, repl, dry_run=True)\nids = [o.id for o in dry.occurrences]\nif not ids:\n    return  # nothing to replace; skip apply\nagent.replace_content(needle, repl, occurrence_ids=ids)","typeGuard":"def has_selection(ids) -> bool:\n    return ids is not None and len(ids) > 0","tryCatchPattern":"try:\n    agent.replace_content(needle, repl, occurrence_ids=ids)\nexcept ValueError as e:\n    if \"occurrence_ids is empty\" in str(e):\n        agent.replace_content(needle, repl)  # or abort\n    else:\n        raise","preventionTips":["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"],"tags":["validation","replace","empty-input"],"backgroundTag":"empty-occurrence-selection","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}