oraios/serena · warning · FileExistsError
Project with path {project_root} was already added with name
Error message
Project with path {project_root} was already added with name '{already_registered_project.project_name}'. What it means
add_project_from_path() prevents duplicate registrations: if a project with the same resolved root path is already present in self.projects, it raises FileExistsError reporting the path and the name it was registered under. Registering the same directory twice would create duplicate project entries in serena_config.yml.
Source
Thrown at src/serena/config/serena_config.py:1270
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))
return new_project
def remove_project(self, project_name: str) -> None:
# find the index of the project with the desired name and remove itView on GitHub (pinned to 7fcbca7e62)
Solutions
- Before adding, scan config.projects for an entry whose project_root matches the resolved path and reuse it (get_registered_project(path)) instead of adding.
- Catch FileExistsError and treat it as success: fetch the existing project via get_registered_project(project_root).
- Remove the existing registration first with remove_project(existing.project_name) if you intend to re-add it fresh.
Example fix
// before
config.add_project_from_path('/repos/app') # FileExistsError on rerun
// after
try:
config.add_project_from_path('/repos/app')
except FileExistsError:
project = config.get_registered_project('/repos/app') Defensive patterns
Strategy: try-catch
Validate before calling
from pathlib import Path resolved = str(Path(project_root).resolve()) already = any(str(p.project_root) == resolved for p in config.projects)
Type guard
def is_registered(config, root) -> bool:
from pathlib import Path
r = str(Path(root).resolve())
return any(str(p.project_root) == r for p in config.projects) Try / catch
try:
config.add_project_from_path(project_root)
except FileExistsError:
project = config.get_registered_project(project_root) # reuse existing Prevention
- Check is_registered() before every add_project_from_path call
- Make registration scripts idempotent (add-or-get pattern)
- Remember resolve() normalizes equivalent paths, so aliases still collide
When it happens
Trigger: Calling add_project_from_path('/repos/app') when '/repos/app' (or a path string that resolves identically) is already registered — including calling activate_project_from_path_or_name() with an already-registered path.
Common situations: Re-running an onboarding/activation script without idempotency; two code paths both adding the project during startup; equivalent paths like /repos/app vs /repos/../repos/app resolving to the same root (resolve() normalizes them).
Related errors
- Context file not found: {path.resolve()}
- Cannot use both fixed_tools and excluded_tools/included_opti
- Unknown language backend '{backend_str}': valid values are {
- Invalid line_ending: {value!r}. Valid values are: {valid}
- Cannot use interactive mode with asynchronous auto-generatio
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/b39547dccb2eebb8.
Report an issue: GitHub.