home-assistant/core · error · InvalidUser

user_not_found

user_not_found

Error message

user_not_found

What it means

InvalidUser with translation_key user_not_found, raised by Data.async_remove_auth (homeassistant/auth/providers/homeassistant.py:226) when the username to delete does not exist in the local auth provider's user store. Usernames are normalized (strip + casefold) before lookup, so only a truly absent (or differently spelled-but-normalizing-equal) name passes.

Source

Thrown at homeassistant/auth/providers/homeassistant.py:226

            {
                "username": username,
                "password": self.hash_password(password, True).decode(),
            }
        )

    @callback
    def async_remove_auth(self, username: str) -> None:
        """Remove authentication."""
        username = self.normalize_username(username)

        index = None
        for i, user in enumerate(self.users):
            if self.normalize_username(user["username"]) == username:
                index = i
                break

        if index is None:
            raise InvalidUser(translation_key="user_not_found")

        self.users.pop(index)

    def change_password(self, username: str, new_password: str) -> None:
        """Update the password.

        Raises InvalidUser if user cannot be found.
        """
        username = self.normalize_username(username)

        for user in self.users:
            if self.normalize_username(user["username"]) == username:
                user["password"] = self.hash_password(new_password, True).decode()
                break
        else:
            raise InvalidUser(translation_key="user_not_found")

    @callback

View on GitHub (pinned to 58a3fdb3ea)

Solutions

  1. Check membership first: `if all(prv.normalize_username(u['username']) != provider.data.normalize_username(username) for u in provider.data.users): skip` — or simply treat user_not_found as success (idempotent delete)
  2. Catch InvalidUser and inspect translation_key == 'user_not_found' to tolerate double-delete

Example fix

// before
provider.data.async_remove_auth(username)  # raises if absent

# after
from homeassistant.auth.providers.homeassistant import InvalidUser
try:
    provider.data.async_remove_auth(username)
except InvalidUser as err:
    if err.translation_key != "user_not_found":
        raise
Defensive patterns

Strategy: try-catch

Validate before calling

normalized = provider.normalize_username(username)
exists = any(
    provider.normalize_username(u["username"]) == normalized
    for u in provider.data.users
)
if exists:
    provider.data.async_remove_auth(username)

Try / catch

from homeassistant.auth.providers.homeassistant import InvalidUser
try:
    provider.data.async_remove_auth(username)
except InvalidUser as err:
    if err.translation_key != "user_not_found":
        raise
    # already gone: nothing to do

Prevention

When it happens

Trigger: Calling provider.data.async_remove_auth(username) for a name not in the storage; name already removed by a prior call; passing the HA user name instead of the provider username.

Common situations: Onboarding/offboarding scripts deleting an already-deleted account; mismatch between auth provider usernames and user-facing names; concurrent deletion flows.

Related errors


AI-assisted analysis of home-assistant/core@58a3fdb3ea (2026-08-14). Data as JSON: /api/errors/b46b43253e0f2105. Report an issue: GitHub.