oraios/serena · error · FileNotFoundError

Project root not found: {project_root}

Error message

Project root not found: {project_root}

What it means

Serena's ProjectConfig.autogenerate() resolves the given project_root path and raises FileNotFoundError when that directory does not exist on disk. The library refuses to auto-generate a project configuration file (.serena/project.yml) for a non-existent root, since language detection and file scanning depend on a real directory. The message includes the resolved absolute path so you can see exactly what was looked for.

Source

Thrown at src/serena/config/serena_config.py:441

        """
        Autogenerate a project configuration for a given project root.

        :param project_root: the path to the project root
        :param serena_config: the global Serena configuration
        :param project_name: the name of the project; if None, the name of the project will be the name of the directory
            containing the project
        :param languages: the languages of the project; if None, they will be determined automatically
        :param save_to_disk: whether to save the project configuration to disk
        :param interactive: whether to run in interactive CLI mode, asking the user for input where appropriate
        :param asynchronous: whether to run in asynchronous mode, where time-consuming configuration parts (currently only the
            determination of the list of programming languages) are determined in a background thread and initialised as empty
        :return: the project configuration
        """
        if interactive and asynchronous:
            raise ValueError("Cannot use interactive mode with asynchronous auto-generation")
        project_root = Path(project_root).resolve()
        if not project_root.exists():
            raise FileNotFoundError(f"Project root not found: {project_root}")
        with LogTime("Project configuration auto-generation", logger=log):
            log.info("Project root: %s", project_root)
            project_folder_name = project_root.name
            project_name = project_name or project_folder_name
            use_asynchronous_language_determination = False
            if languages is None:
                if asynchronous:
                    use_asynchronous_language_determination = True
                    languages_to_use = []  # temporarily empty, will be determined in background thread
                else:
                    determined_languages = cls._determine_project_language_servers(
                        str(project_root), interactive=interactive, serena_config=serena_config
                    )
                    languages_to_use = [l.value for l in determined_languages]
            else:
                languages_to_use = [lang.value for lang in languages]
            config_with_comments, _ = cls._load_yaml_dict(PROJECT_TEMPLATE_FILE)
            config_with_comments["project_name"] = project_name

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Verify the directory exists (ls the resolved path printed in the message) and fix typos in the path
  2. Create the directory first (mkdir -p <root>) if you intend to initialize a new project there
  3. Pass an absolute path or resolve relative paths against the correct working directory before calling autogenerate/load
  4. If the folder moved, update the path in whatever config/CLI/IDE setting references it

Example fix

// before
config = ProjectConfig.autogenerate(project_root="~/code/my-projet", interactive=False)
// after
root = Path("~/code/my-project").expanduser().resolve()
assert root.exists(), f"missing project root: {root}"
config = ProjectConfig.autogenerate(project_root=str(root), interactive=False)
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
root = Path(project_root).expanduser().resolve()
if not root.is_dir():
    raise SystemExit(f"Project root does not exist: {root}. Create it or fix the path before calling autogenerate.")

Type guard

def project_root_exists(path: str | Path) -> bool:
    p = Path(path).expanduser().resolve()
    return p.exists() and p.is_dir()

Try / catch

try:
    config = ProjectConfig.autogenerate(project_root=str(root), interactive=False)
except FileNotFoundError as e:
    logger.error("Project root missing: %s — create it with mkdir -p or correct the path", e)
    raise

Prevention

When it happens

Trigger: Calling ProjectConfig.autogenerate(project_root=...) (directly or via ProjectConfig.load or _create_project) with a path that does not exist after Path(project_root).resolve() — e.g. a typo, a deleted/moved directory, or a relative path resolved against the wrong working directory. Also triggered by tests test_autogenerate_empty_directory and friends when the fixture root is absent.

Common situations: Passing a path relative to a different CWD than expected (IDE vs CLI), a project folder that was renamed or removed, a typo like './my-projet', or constructing the path from an env var that is unset. Also common when creating a brand-new project: users point autogenerate at a folder they intend to create rather than one that exists.

Related errors


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