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

  1. If the existing bundle is stale or you intend to replace it, call create_bundle(..., overwrite=True).
  2. If the existing bundle must be kept, delete it first with delete_bundle(name) or pick a different bundle name.
  3. 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

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


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/46e73225bab49b04. Report an issue: GitHub.