{"record":{"id":"fcbdd3202fd18a2d","repo":"oraios/serena","slug":"expected-count-expected-count-but-the-pattern-m","errorCode":null,"errorMessage":"expected_count={expected_count}, but the pattern matches {len(occurrences)} occurrence(s) - NO changes were applied. Review the prospective changes below; re-issue with the corrected expectation, a refined pattern, or occurrence_ids selecting the intended subset.\n{listing}","messagePattern":"expected_count=(.+?), but the pattern matches (.+?) occurrence\\(s\\) - NO changes were applied\\. Review the prospective changes below; re-issue with the corrected expectation, a refined pattern, or occurrence_ids selecting the intended subset\\.\n(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/serena/tools/file_tools.py","lineNumber":305,"sourceCode":"                    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]\n        if ambiguous:\n            listing = self._render_listing(replacer, occurrences, contents, max_answer_chars, dry_run=False)\n            raise ValueError(\n                f\"{len(ambiguous)} occurrence(s) are ambiguous (the pattern matches again inside the matched text, \"\n                f\"indicating possible over-matching) - NO changes were applied. Review the prospective changes below \"\n                f\"and either refine the pattern or explicitly select occurrences via occurrence_ids.\\n{listing}\"\n            )\n        return self._apply_occurrences(replacer, occurrences, contents, needle, repl)\n\n    def _collect_files(self, relative_path: str, paths_include_glob: str, paths_exclude_glob: str) -> list[tuple[str, str]]:\n        \"\"\"Collects (relative_path, content) pairs of the non-ignored files in scope, in sorted path order.\"\"\"\n        relative_path = relative_path.strip()\n        if relative_path:","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/serena/tools/file_tools.py#L287-L323","documentation":"apply() supports an expected_count safety check: if specified (>= 0) and the number of pattern matches differs from it, no changes are applied and a ValueError including a dry-run-style listing of the prospective changes is raised. This protects against unintended bulk replacements when the file drifted or the pattern is broader than expected.","triggerScenarios":"Calling replace_content with expected_count=N where the pattern matches M != N occurrences; the target text appears more times than expected (e.g. in comments, tests, or generated code); a previous edit already changed the count.","commonSituations":"Refactoring scripts written against an earlier file version; needles that also match inside strings/comments/docstrings; case-insensitive or wildcard patterns matching more than the single intended site.","solutions":["Inspect the listing in the error to see every match, then re-issue with the correct expected_count","Refine the pattern (or add path/glob restrictions) so it matches exactly the intended occurrences","Use occurrence_ids from a dry run to select exactly the intended subset","Set expected_count=-1 (omit) if the count is genuinely variable and the replacement is safe for all matches"],"exampleFix":"// before\nagent.replace_content(needle=\"oldName\", repl=\"newName\", expected_count=1)\n// after\nlisting = agent.replace_content(needle=\"oldName\", repl=\"newName\", dry_run=True)\n# review matches, then select subset:\nagent.replace_content(needle=\"oldName\", repl=\"newName\",\n                      occurrence_ids=[listing.occurrences[0].id])","handlingStrategy":"try-catch","validationCode":"dry = agent.replace_content(needle, repl, dry_run=True)\nassert len(dry.occurrences) == expected_count, \\\n    f\"{len(dry.occurrences)} matches, expected {expected_count}\"","typeGuard":"def count_matches(needle, path) -> int:\n    return len(agent.search_for_pattern(needle, path=path))","tryCatchPattern":"try:\n    agent.replace_content(needle, repl, expected_count=n)\nexcept ValueError as e:\n    if \"expected_count\" in str(e):\n        # listing of matches is embedded in the message; refine pattern or ids\n        dry = agent.replace_content(needle, repl, dry_run=True)\n        agent.replace_content(needle, repl, occurrence_ids=[o.id for o in dry.occurrences[:n]])\n    else:\n        raise","preventionTips":["Dry-run first and verify the match count matches expectations","Constrain patterns with paths/globs to narrow scope","Use occurrence_ids for surgical subset replacements"],"tags":["safety-check","replace","count-mismatch"],"backgroundTag":"pattern-count-mismatch","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}