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

  1. Pass the project root directory, not a file — if you have a config file path, use its .parent.
  2. Guard the call: resolve the path and assert p.is_dir() before registering.
  3. 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

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


AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29). Data as JSON: /api/errors/331de4b02c09bf42. Report an issue: GitHub.