{"record":{"id":"46e73225bab49b04","repo":"NousResearch/hermes-agent","slug":"bundle-already-exists-at-path","errorCode":null,"errorMessage":"Bundle already exists at {path}","messagePattern":"Bundle already exists at (.+?)","errorType":"exception","errorClass":"FileExistsError","httpStatus":null,"severity":"error","filePath":"agent/skill_bundles.py","lineNumber":405,"sourceCode":"    description: str = \"\",\n    instruction: str = \"\",\n    overwrite: bool = False,\n) -> Path:\n    \"\"\"Write a bundle to disk and invalidate the cache.\n\n    Raises ``FileExistsError`` if the target exists and ``overwrite`` is\n    False. Raises ``ValueError`` if the inputs are unusable.\n    \"\"\"\n    name = (name or \"\").strip()\n    if not name:\n        raise ValueError(\"Bundle name is required\")\n    cleaned_skills = [str(s).strip() for s in skills if str(s).strip()]\n    if not cleaned_skills:\n        raise ValueError(\"Bundle must reference at least one skill\")\n\n    path = bundle_path_for(name)\n    if path.exists() and not overwrite:\n        raise FileExistsError(f\"Bundle already exists at {path}\")\n\n    path.parent.mkdir(parents=True, exist_ok=True)\n    payload: Dict[str, Any] = {\"name\": name, \"skills\": cleaned_skills}\n    if description:\n        payload[\"description\"] = description\n    if instruction:\n        payload[\"instruction\"] = instruction\n\n    path.write_text(\n        yaml.safe_dump(payload, sort_keys=False, allow_unicode=True),\n        encoding=\"utf-8\",\n    )\n    scan_bundles()  # refresh cache\n    return path\n\n\ndef delete_bundle(name: str) -> Path:\n    \"\"\"Delete a bundle by name. Returns the deleted path.","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/skill_bundles.py#L387-L423","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ncreate_bundle(\"research\", skills=[\"web_search\", \"citation\"])\n\n# after\nif get_bundle(\"research\") is None:\n    create_bundle(\"research\", skills=[\"web_search\", \"citation\"])\nelse:\n    create_bundle(\"research\", skills=[\"web_search\", \"citation\"], overwrite=True)","handlingStrategy":"validation","validationCode":"from agent.skill_bundles import get_bundle\n\nif get_bundle(name) is not None:\n    # decide explicitly: skip, delete, or overwrite\n    create_bundle(name, skills, overwrite=True)\nelse:\n    create_bundle(name, skills)","typeGuard":null,"tryCatchPattern":"try:\n    create_bundle(name, skills)\nexcept FileExistsError as exc:\n    # idempotent provisioning: overwrite or skip\n    create_bundle(name, skills, overwrite=True)","preventionTips":["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."],"tags":["skills","bundles","filesystem","file-exists"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}