{"record":{"id":"6d683f79b40372c9","repo":"oraios/serena","slug":"relative-path-relative-path-does-not-exist-6d683f","errorCode":null,"errorMessage":"Relative path {relative_path} does not exist.","messagePattern":"Relative path (.+?) does not exist\\.","errorType":"validation","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"src/serena/tools/file_tools.py","lineNumber":327,"sourceCode":"            )\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:\n            self.project.validate_relative_path(relative_path, require_not_ignored=True)\n        abs_path = os.path.join(self.get_project_root(), relative_path)\n        if not os.path.exists(abs_path):\n            raise FileNotFoundError(f\"Relative path {relative_path} does not exist.\")\n        if os.path.isfile(abs_path):\n            rel_paths = [relative_path]\n        else:\n            _dirs, rel_paths = scan_directory(\n                path=abs_path,\n                recursive=True,\n                is_ignored_dir=self.project.is_ignored_path,\n                is_ignored_file=self.project.is_ignored_path,\n                relative_to=self.get_project_root(),\n            )\n        include_glob_matcher = GlobMatcher(paths_include_glob.strip()) if paths_include_glob.strip() else None\n        exclude_glob_matcher = GlobMatcher(paths_exclude_glob.strip()) if paths_exclude_glob.strip() else None\n        files: list[tuple[str, str]] = []\n        for path in sorted(rel_paths):\n            if include_glob_matcher and not include_glob_matcher.matches(path):\n                continue\n            if exclude_glob_matcher and exclude_glob_matcher.matches(path):\n                continue","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/serena/tools/file_tools.py#L309-L345","documentation":"_collect_files (used by replace_content's scope collection) validates that the given relative path exists under the project root after ignore-rule validation. If it does not exist, a FileNotFoundError is raised before any matching or replacement happens.","triggerScenarios":"Passing path=\"missing/dir\" or a typo'd file name to replace_content; passing an empty-string path that normalizes to project root but with a stripped/wrong value; referencing a path that is gitignored or outside the validated project root (caught earlier by validate_relative_path).","commonSituations":"Path separators mismatch (Windows-style backslashes on Linux); the file was moved/renamed by a prior automated edit; passing an absolute path where only project-relative paths are accepted.","solutions":["Correct the relative path (relative to the project root, forward slashes) and retry","Verify existence with os.path.exists(os.path.join(project_root, relative_path)) before the call","List available files (e.g. via search_for_pattern or directory listing) to find the right path","If the file should exist, restore it (git checkout) — it may have been deleted by a previous edit"],"exampleFix":"// before\nagent.replace_content(needle=\"foo\", repl=\"bar\", path=\"src/ap.py\")\n// after\nrel = \"src/app.py\"\nassert os.path.exists(os.path.join(project_root, rel)), rel\nagent.replace_content(needle=\"foo\", repl=\"bar\", path=rel)","handlingStrategy":"validation","validationCode":"import os\nabs_path = os.path.join(project_root, relative_path)\nif not os.path.exists(abs_path):\n    raise FileNotFoundError(abs_path)\nagent.replace_content(needle, repl, path=relative_path)","typeGuard":"def path_exists(rel: str, root: str) -> bool:\n    return os.path.exists(os.path.join(root, rel.strip()))","tryCatchPattern":"try:\n    agent.replace_content(needle, repl, path=rel)\nexcept FileNotFoundError as e:\n    if \"does not exist\" in str(e):\n        rel = find_correct_path(rel)  # list/search project files\n        agent.replace_content(needle, repl, path=rel)\n    else:\n        raise","preventionTips":["Keep paths project-relative with forward slashes","Re-verify paths after automated moves/renames","List project files to confirm path spelling before edits"],"tags":["filesystem","path","validation"],"backgroundTag":"file-not-found","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}