NousResearch/hermes-agent · error · FileExistsError
Bundle already exists at {path}
Error message
Bundle already exists at {path} What it means
Raised by create_bundle() in agent/skill_bundles.py when saving a skill bundle whose target YAML file already exists on disk and the overwrite flag is False. It is a guard against silently clobbering an existing bundle's contents. The path is derived from bundle_path_for(name), which slug-normalizes the name.
Source
Thrown at agent/skill_bundles.py:405
description: str = "",
instruction: str = "",
overwrite: bool = False,
) -> Path:
"""Write a bundle to disk and invalidate the cache.
Raises ``FileExistsError`` if the target exists and ``overwrite`` is
False. Raises ``ValueError`` if the inputs are unusable.
"""
name = (name or "").strip()
if not name:
raise ValueError("Bundle name is required")
cleaned_skills = [str(s).strip() for s in skills if str(s).strip()]
if not cleaned_skills:
raise ValueError("Bundle must reference at least one skill")
path = bundle_path_for(name)
if path.exists() and not overwrite:
raise FileExistsError(f"Bundle already exists at {path}")
path.parent.mkdir(parents=True, exist_ok=True)
payload: Dict[str, Any] = {"name": name, "skills": cleaned_skills}
if description:
payload["description"] = description
if instruction:
payload["instruction"] = instruction
path.write_text(
yaml.safe_dump(payload, sort_keys=False, allow_unicode=True),
encoding="utf-8",
)
scan_bundles() # refresh cache
return path
def delete_bundle(name: str) -> Path:
"""Delete a bundle by name. Returns the deleted path.View on GitHub (pinned to c896c09c42)
Solutions
- If the existing bundle is stale or you intend to replace it, call create_bundle(..., overwrite=True).
- If the existing bundle must be kept, delete it first with delete_bundle(name) or pick a different bundle name.
- Check for an existing bundle before creating: get_bundle(name) returns non-None when one already exists.
Example fix
# before
create_bundle("research", skills=["web_search", "citation"])
# after
if get_bundle("research") is None:
create_bundle("research", skills=["web_search", "citation"])
else:
create_bundle("research", skills=["web_search", "citation"], overwrite=True) Defensive patterns
Strategy: validation
Validate before calling
from agent.skill_bundles import get_bundle
if get_bundle(name) is not None:
# decide explicitly: skip, delete, or overwrite
create_bundle(name, skills, overwrite=True)
else:
create_bundle(name, skills) Try / catch
try:
create_bundle(name, skills)
except FileExistsError as exc:
# idempotent provisioning: overwrite or skip
create_bundle(name, skills, overwrite=True) Prevention
- Treat bundle creation as an upsert: always decide overwrite behavior up front.
- In scripts, check get_bundle(name) before create_bundle to make provisioning idempotent.
- Remember names are slug-normalized — 'My Bundle' and 'my-bundle' collide.
When it happens
Trigger: Calling create_bundle(name, skills=[...]) (or a wrapper CLI/plugin command) with a name whose slug matches an existing bundle file under the Hermes skills bundles directory, without passing overwrite=True.
Common situations: Re-running a setup script or plugin that installs the same bundle twice; creating a bundle whose name slug-collides with an existing one (e.g. 'My Bundle' vs 'my-bundle'); CI pipelines that provision bundles idempotently but forget overwrite=True.
Related errors
- No bundle at {path}
- Hermes backend did not become ready: ${detail}
- Not a directory: ${watchDir}
- Could not create directory: ${error.message}
- Invalid rename
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/46e73225bab49b04.
Report an issue: GitHub.