{"record":{"id":"8757289a81b404e7","repo":"FoundationAgents/MetaGPT","slug":"directory-dir-path-not-found","errorCode":null,"errorMessage":"Directory {dir_path} not found","messagePattern":"Directory (.+?) not found","errorType":"exception","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"metagpt/tools/libs/editor.py","lineNumber":1007,"sourceCode":"            start=None,\n            end=None,\n            content=content,\n            is_insert=False,\n            is_append=True,\n        )\n        self.resource.report(file_name, \"path\")\n        return ret_str\n\n    def search_dir(self, search_term: str, dir_path: str = \"./\") -> str:\n        \"\"\"Searches for search_term in all files in dir. If dir is not provided, searches in the current directory.\n\n        Args:\n            search_term: str: The term to search for.\n            dir_path: str: The path to the directory to search.\n        \"\"\"\n        dir_path = self._try_fix_path(dir_path)\n        if not dir_path.is_dir():\n            raise FileNotFoundError(f\"Directory {dir_path} not found\")\n        matches = []\n        for root, _, files in os.walk(dir_path):\n            for file in files:\n                if file.startswith(\".\"):\n                    continue\n                file_path = Path(root) / file\n                with file_path.open(\"r\", errors=\"ignore\") as f:\n                    for line_num, line in enumerate(f, 1):\n                        if search_term in line:\n                            matches.append((file_path, line_num, line.strip()))\n\n        if not matches:\n            return f'No matches found for \"{search_term}\" in {dir_path}'\n\n        num_matches = len(matches)\n        num_files = len(set(match[0] for match in matches))\n\n        if num_files > 100:","sourceCodeStart":989,"sourceCodeEnd":1025,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/tools/libs/editor.py#L989-L1025","documentation":"Raised by Editor.search_dir after path normalization when dir_path does not exist or is not a directory. The tool recursively walks the directory (skipping dotfiles) to grep for search_term, so a valid directory is a hard prerequisite.","triggerScenarios":"editor.search_dir('foo', './sr c') typo paths; searching a directory that was never created or was deleted; passing a file path instead of a directory; relative path resolved against an unexpected CWD.","commonSituations":"Agents guessing at repo layout (searching './src' when the code is at './lib'); running from a different working directory than assumed; renaming or moving directories between steps.","solutions":["Check Path(dir_path).is_dir() before calling, or list the parent to find the right directory name","Pass an absolute directory path to avoid CWD-dependent resolution","Default to './' when unsure, then narrow based on the matches"],"exampleFix":"// before\neditor.search_dir('parse_args', './source')  # FileNotFoundError\n\n// after\nd = Path('./source')\nroot = d if d.is_dir() else Path('.')\neditor.search_dir('parse_args', str(root))","handlingStrategy":"validation","validationCode":"from pathlib import Path\nd = Path(dir_path)\nif not d.is_dir():\n    d = Path('.')\neditor.search_dir(search_term, str(d))","typeGuard":"def is_searchable_dir(p: str) -> bool:\n    return Path(p).is_dir()","tryCatchPattern":"try:\n    editor.search_dir(term, dir_path)\nexcept FileNotFoundError:\n    editor.search_dir(term, './')  # fall back to CWD-wide search","preventionTips":["Verify directory names with a listing before searching","Pass absolute directory paths from a known workspace root","Fall back to './' and refine from the match paths when layout is unknown"],"tags":["editor","search","filesystem","path","metagpt"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}