oraios/serena · error · FileNotFoundError
Error: Path is not a directory: {project_root}
Error message
Error: Path is not a directory: {project_root} What it means
add_project_from_path() only registers directories, not files. After confirming existence, it checks Path.is_dir() and raises FileNotFoundError with 'Error: Path is not a directory' when the resolved path points to a regular file, symlink-to-file, or other non-directory.
Source
Thrown at src/serena/config/serena_config.py:1266
self._persist_projects()
def add_project_from_path(self, project_root: Path | str, asynchronous_autogen: bool = False) -> "Project":
"""
Adds a new project to the Serena configuration from a given path, auto-generating the project
with defaults if it does not exist.
Will raise a FileExistsError if a project already exists at the path.
:param project_root: the path to the project to add
:param asynchronous_autogen: whether to use asynchronous auto-generation for the project configuration
:return: the project that was added
"""
from ..project import Project
project_root = Path(project_root).resolve()
if not project_root.exists():
raise FileNotFoundError(f"Error: Path does not exist: {project_root}")
if not project_root.is_dir():
raise FileNotFoundError(f"Error: Path is not a directory: {project_root}")
for already_registered_project in self.projects:
if str(already_registered_project.project_root) == str(project_root):
raise FileExistsError(
f"Project with path {project_root} was already added with name '{already_registered_project.project_name}'."
)
autogen = ProjectConfigAutoGenerationMode.ASYNCHRONOUS if asynchronous_autogen else ProjectConfigAutoGenerationMode.SYNCHRONOUS
project_config = ProjectConfig.load(project_root, serena_config=self, autogen=autogen)
new_project = Project(
project_root=str(project_root),
project_config=project_config,
is_newly_created=True,
serena_config=self,
)
self.add_registered_project(RegisteredProject.from_project_instance(new_project))
View on GitHub (pinned to 7fcbca7e62)
Solutions
- Pass the project root directory, not a file — if you have a config file path, use its .parent.
- Guard the call: resolve the path and assert p.is_dir() before registering.
- Check for stray symlinks/files where you expect the project directory.
Example fix
// before
config.add_project_from_path('/repos/app/serena_project.yml')
// after
p = Path('/repos/app/serena_project.yml')
config.add_project_from_path(p.parent) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
root = Path(project_root).expanduser().resolve()
if not root.is_dir():
if root.is_file():
root = root.parent # use the containing directory Type guard
def is_directory(p) -> bool:
from pathlib import Path
return Path(p).expanduser().resolve().is_dir() Try / catch
try:
config.add_project_from_path(project_root)
except FileNotFoundError as e:
if 'not a directory' in str(e):
config.add_project_from_path(Path(project_root).parent)
else:
raise Prevention
- Never pass file paths (e.g. serena_project.yml) where a project root is expected
- Use path.parent when starting from a config-file path
- Check is_dir(), not just exists(), in pre-flight validation
When it happens
Trigger: Calling add_project_from_path('/repos/app/README.md') or passing a file path to activate_project_from_path_or_name(); e.g. passing a config file path instead of the project root.
Common situations: Passing serena_project.yml itself instead of its parent directory; a broken symlink resolving to a file; shell autocompletion picking a file; scripts concatenating paths incorrectly.
Related errors
- Error: Path does not exist: {project_root}
- Project root not found: {project_root}
- Relative path {start_path} not found.
- File or directory {relative_path} does not exist in the proj
- Mode file not found: {path.resolve()}
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/331de4b02c09bf42.
Report an issue: GitHub.