{"record":{"id":"0bb18f4dc2de4233","repo":"home-assistant/core","slug":"blueprint-already-exists","errorCode":null,"errorMessage":"Blueprint already exists","messagePattern":"Blueprint already exists","errorType":"exception","errorClass":"FileAlreadyExists","httpStatus":null,"severity":"warning","filePath":"homeassistant/components/blueprint/models.py","lineNumber":346,"sourceCode":"        path = self.blueprint_folder / blueprint_path\n        await self.hass.async_add_executor_job(path.unlink)\n        self._blueprints[blueprint_path] = None\n\n    def _create_file(\n        self, blueprint: Blueprint, blueprint_path: str, allow_override: bool\n    ) -> bool:\n        \"\"\"Create blueprint file.\n\n        Returns true if the action overrides an existing blueprint.\n        \"\"\"\n\n        path = pathlib.Path(\n            self.hass.config.path(BLUEPRINT_FOLDER, self.domain, blueprint_path)\n        )\n        exists = path.exists()\n\n        if not allow_override and exists:\n            raise FileAlreadyExists(self.domain, blueprint_path)\n\n        path.parent.mkdir(parents=True, exist_ok=True)\n        path.write_text(blueprint.yaml(), encoding=\"utf-8\")\n        return exists\n\n    async def async_add_blueprint(\n        self, blueprint: Blueprint, blueprint_path: str, allow_override: bool = False\n    ) -> bool:\n        \"\"\"Add a blueprint.\"\"\"\n        overrides_existing = await self.hass.async_add_executor_job(\n            self._create_file, blueprint, blueprint_path, allow_override\n        )\n\n        self._blueprints[blueprint_path] = blueprint\n\n        if overrides_existing:\n            await self._reload_blueprint_consumers(self.hass, blueprint_path)\n","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/home-assistant/core/blob/58a3fdb3ea0538617f0a07efcfba6294de64fd59/homeassistant/components/blueprint/models.py#L328-L364","documentation":"FileAlreadyExists is raised by _create_file when a blueprint file already exists at the target path and allow_override is False. This guards the import flow so a new import does not silently clobber a local, possibly hand-edited blueprint.","triggerScenarios":"Importing a blueprint whose computed path (often author/package/filename.yaml) already exists in config/blueprints/<domain>/ without passing allow_override=True (the UI shows a confirm-overwrite prompt that sets it).","commonSituations":"Re-importing an updated community blueprint; importing a different blueprint that resolves to the same filename; double-clicking import.","solutions":["If overwrite is intended, pass allow_override=True (in the UI, confirm the 'already exists, overwrite?' dialog)","Otherwise rename the existing file first, then import to get both side by side","Check for a stale copy you no longer need and delete it (after handling BlueprintInUse)"],"exampleFix":"# before\nawait manager.async_add_blueprint(bp, \"domotics/motion.yaml\")\n\n# after\nawait manager.async_add_blueprint(bp, \"domotics/motion.yaml\", allow_override=True)","handlingStrategy":"try-catch","validationCode":"from pathlib import Path\n\ndef blueprint_target_free(hass, domain: str, path: str) -> bool:\n    return not (Path(hass.config.path(\"blueprints\", domain)) / path).exists()","typeGuard":null,"tryCatchPattern":"from homeassistant.components.blueprint.errors import FileAlreadyExists\ntry:\n    await manager.async_add_blueprint(bp, path)\nexcept FileAlreadyExists:\n    # ask user to confirm, then retry with allow_override=True","preventionTips":["In UI flows, always offer the overwrite confirmation instead of forcing allow_override","Rename rather than overwrite when you want to keep local edits"],"tags":["blueprint","import","file-exists"],"backgroundTag":null,"analyzedSha":"58a3fdb3ea0538617f0a07efcfba6294de64fd59","analyzedAt":"2026-08-14T20:54:38.818Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}