{"record":{"id":"76bb67d958d91532","repo":"oraios/serena","slug":"expected-a-file-path-but-got-a-directory-path-r","errorCode":null,"errorMessage":"Expected a file path, but got a directory path: {relative_path}. ","messagePattern":"Expected a file path, but got a directory path: (.+?)\\. ","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/serena/tools/symbol_tools.py","lineNumber":107,"sourceCode":"            shortened_results = [make_depth_0_result, make_kind_counts]\n\n        return self._limit_length(result_json_str, max_answer_chars, shortened_result_factories=shortened_results)\n\n    def get_symbol_overview(self, relative_path: str, depth: int = 0) -> list[LanguageServerSymbol.OutputDict]:\n        \"\"\"\n        :param relative_path: relative path to a source file\n        :param depth: the depth up to which descendants shall be retrieved\n        :return: a list of symbol dictionaries representing the symbol overview of the file\n        \"\"\"\n        symbol_retriever = self.create_language_server_symbol_retriever()\n\n        # The symbol overview is capable of working with both files and directories,\n        # but we want to ensure that the user provides a file path.\n        file_path = os.path.join(self.project.project_root, relative_path)\n        if not os.path.exists(file_path):\n            raise FileNotFoundError(f\"File or directory {relative_path} does not exist in the project.\")\n        if os.path.isdir(file_path):\n            raise ValueError(f\"Expected a file path, but got a directory path: {relative_path}. \")\n        if not symbol_retriever.can_analyze_file(relative_path):\n            raise ValueError(\n                f\"Cannot extract symbols from file {relative_path}. Active language servers: {[l.value for l in self.agent.get_active_language_server_ids()]}\"\n            )\n\n        symbols = symbol_retriever.get_symbol_overview(relative_path)[relative_path]\n\n        def child_inclusion_predicate(s: LanguageServerSymbol) -> bool:\n            return not s.is_low_level()\n\n        symbol_dicts = []\n        for symbol in symbols:\n            symbol_dicts.append(\n                symbol.to_dict(\n                    name_path=False,\n                    name=True,\n                    depth=depth,\n                    kind=True,","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/serena/tools/symbol_tools.py#L89-L125","documentation":"get_symbol_overview requires a file path; passing a directory path raises ValueError even though the low-level symbol retriever supports directories. The tool intentionally narrows the contract to files so callers get a predictable, file-scoped symbol listing.","triggerScenarios":"Calling get_symbol_overview with relative_path pointing to a directory (e.g. 'src' or 'src/'), or a path that exists but is a directory rather than a file.","commonSituations":"User asks 'show me all symbols in the src folder'; agent passes the project root '.'; glob-like or trailing-slash paths that resolve to directories.","solutions":["Pass an individual file path instead of a directory","Iterate over directory files yourself and call get_symbol_overview per file","Use a directory-capable listing (e.g. the JetBrains overview tool or find_file) to enumerate files first"],"exampleFix":"// before\nget_symbol_overview.apply(relative_path='src')\n// ValueError: Expected a file path...\n\n// after\nfor f in Path('src').rglob('*.py'):\n    overview = get_symbol_overview.apply(relative_path=str(f))","handlingStrategy":"validation","validationCode":"from pathlib import Path\np = Path(project_root) / relative_path\nif p.is_dir():\n    files = [str(f.relative_to(project_root)) for f in p.rglob('*') if f.is_file()]\n    overviews = [symbol_tool.get_symbol_overview(relative_path=f) for f in files]\nelse:\n    overview = symbol_tool.get_symbol_overview(relative_path=relative_path)","typeGuard":"def is_file_path(rel: str, root: str) -> bool:\n    p = Path(root) / rel\n    return p.is_file()","tryCatchPattern":"try:\n    overview = symbol_tool.get_symbol_overview(relative_path=rel)\nexcept ValueError as e:\n    if 'directory path' in str(e):\n        overview = [symbol_tool.get_symbol_overview(relative_path=str(f))\n                    for f in (Path(root) / rel).rglob('*') if f.is_file()]\n    else:\n        raise","preventionTips":["Check p.is_file() before calling get_symbol_overview","Never pass directory or glob-style paths to this tool","Expand directories into individual file paths first"],"tags":["python","validation","path","symbols"],"backgroundTag":"file-vs-directory-path","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}