{"record":{"id":"9873720f8d6803c7","repo":"home-assistant/core","slug":"cannot-delete-credential-in-use-by-integration-en","errorCode":null,"errorMessage":"Cannot delete credential in use by integration {entry.domain}","messagePattern":"Cannot delete credential in use by integration (.+?)","errorType":"exception","errorClass":"HomeAssistantError","httpStatus":null,"severity":"warning","filePath":"homeassistant/components/application_credentials/__init__.py","lineNumber":121,"sourceCode":"    @override\n    async def _update_data(\n        self, item: dict[str, str], update_data: dict[str, str]\n    ) -> dict[str, str]:\n        \"\"\"Return a new updated data object.\"\"\"\n        raise ValueError(\"Updates not supported\")\n\n    @override\n    async def async_delete_item(self, item_id: str) -> None:\n        \"\"\"Delete item, verifying credential is not in use.\"\"\"\n        if item_id not in self.data:\n            raise collection.ItemNotFound(item_id)\n\n        # Cannot delete a credential currently in use by a ConfigEntry\n        current = self.data[item_id]\n        entries = self.hass.config_entries.async_entries(current[CONF_DOMAIN])\n        for entry in entries:\n            if entry.data.get(\"auth_implementation\") == item_id:\n                raise HomeAssistantError(\n                    f\"Cannot delete credential in use by integration {entry.domain}\"\n                )\n\n        await super().async_delete_item(item_id)\n\n    async def async_import_item(self, info: dict[str, str]) -> None:\n        \"\"\"Import an yaml credential if it does not already exist.\"\"\"\n        suggested_id = self._get_suggested_id(info)\n        if self.id_manager.has_id(slugify(suggested_id)):\n            return\n        await self.async_create_item(info)\n\n    def async_client_credentials(self, domain: str) -> dict[str, ClientCredential]:\n        \"\"\"Return ClientCredentials in storage for the specified domain.\"\"\"\n        credentials = {}\n        for item in self.async_items():\n            if item[CONF_DOMAIN] != domain:\n                continue","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/home-assistant/core/blob/58a3fdb3ea0538617f0a07efcfba6294de64fd59/homeassistant/components/application_credentials/__init__.py#L103-L139","documentation":"Raised as HomeAssistantError when deleting an application credential whose item_id is still referenced by a config entry's data['auth_implementation'] field. This is a safety guard: deleting the credential an entry uses for OAuth would leave the entry unable to obtain tokens, so deletion is refused until the entry is removed or reconfigured to another implementation.","triggerScenarios":"Calling application_credentials/delete for an item where any config entry of the same domain has entry.data['auth_implementation'] == item_id. The lookup iterates all config entries for the credential's domain.","commonSituations":"Rotating OAuth client credentials that are actively used by a configured integration; cleaning up old credentials after reconfiguring but forgetting to remove the config entry that still points at them; multiple config entries sharing one credential.","solutions":["Delete the config entry (or entries) that use the credential first, then retry the credential deletion.","Alternatively, reconfigure/re-add the config entry so it authenticates with a different credential or auth implementation, then delete the old credential.","Find the blocking entry by checking each entry's data['auth_implementation'] for the credential's item_id."],"exampleFix":"for entry in hass.config_entries.async_entries(domain):\n    if entry.data.get(\"auth_implementation\") == item_id:\n        await hass.config_entries.async_remove(entry.entry_id)\nawait app_credentials_collection.async_delete_item(item_id)","handlingStrategy":"validation","validationCode":"def credential_in_use(hass, collection, item_id: str) -> bool:\n    current = collection.data.get(item_id)\n    if current is None:\n        return False\n    for entry in hass.config_entries.async_entries(current[\"domain\"]):\n        if entry.data.get(\"auth_implementation\") == item_id:\n            return True\n    return False","typeGuard":null,"tryCatchPattern":"from homeassistant.exceptions import HomeAssistantError\n\ntry:\n    await collection.async_delete_item(item_id)\nexcept HomeAssistantError as err:\n    if \"in use by integration\" in str(err):\n        # remove/reconfigure the blocking config entry, then retry\n        raise","preventionTips":["Remove config entries before deleting the credentials they use.","Inspect entry.data['auth_implementation'] to find which entry pins a credential.","Automate credential rotation as: reconfigure entry to new credential, then delete old."],"tags":["home-assistant","application-credentials","config-entry","delete-guard"],"backgroundTag":null,"analyzedSha":"58a3fdb3ea0538617f0a07efcfba6294de64fd59","analyzedAt":"2026-08-14T20:54:38.818Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}