home-assistant/core · error · InvalidUsername
username_already_exists
username_already_exists
Error message
username_already_exists
What it means
InvalidUsername with translation_key username_already_exists, raised by Data._validate_new_username (homeassistant/auth/providers/homeassistant.py:263) when the normalized new username equals an existing stored username (comparison is done on normalized forms, so 'Bob' collides with 'bob'). The placeholder username carries the rejected value.
Source
Thrown at homeassistant/auth/providers/homeassistant.py:263
def _validate_new_username(self, new_username: str) -> None:
"""Validate that username is normalized and unique.
Raises InvalidUsername if the new username is invalid.
"""
normalized_username = self.normalize_username(
new_username, force_normalize=True
)
if normalized_username != new_username:
raise InvalidUsername(
translation_key="username_not_normalized",
translation_placeholders={"new_username": new_username},
)
if any(
self.normalize_username(user["username"]) == normalized_username
for user in self.users
):
raise InvalidUsername(
translation_key="username_already_exists",
translation_placeholders={"username": new_username},
)
@callback
def change_username(self, username: str, new_username: str) -> None:
"""Update the username.
Raises InvalidUser if user cannot be found.
Raises InvalidUsername if the new username is invalid.
"""
username = self.normalize_username(username)
self._validate_new_username(new_username)
for user in self.users:
if self.normalize_username(user["username"]) == username:
user["username"] = new_username
assert self._data is not NoneView on GitHub (pinned to 58a3fdb3ea)
Solutions
- Before creating, check `any(provider.data.normalize_username(u["username"]) == new_username.strip().casefold() for u in provider.data.users)` and skip
- For renames, first verify the target name is free; for imports, deduplicate names before writing
Example fix
// before
provider.data.add_auth("alice", password) # alice exists
# after
normalized = "alice"
if not any(provider.data.normalize_username(u["username"]) == normalized for u in provider.data.users):
provider.data.add_auth(normalized, password) Defensive patterns
Strategy: validation
Validate before calling
normalized = new_username.strip().casefold()
if not any(provider.data.normalize_username(u["username"]) == normalized for u in provider.data.users):
provider.data.add_auth(new_username, password) Type guard
def username_is_unique(provider_data, new_username: str) -> bool:
normalized = new_username.strip().casefold()
return not any(
provider_data.normalize_username(u["username"]) == normalized
for u in provider_data.users
) Try / catch
from homeassistant.auth.providers.homeassistant import InvalidUsername
try:
provider.data.add_auth(username, password)
except InvalidUsername as err:
if err.translation_key != "username_already_exists":
raise
# pick a different name or return the existing account Prevention
- Check name availability with a normalized comparison before creating
- Deduplicate names during imports and migrations
When it happens
Trigger: add_auth with a name already in the store; change_username to a name owned by another account; migration scripts re-creating existing users.
Common situations: Idempotent provisioning scripts that don't check first; renames colliding with another user; imports merging two sources with duplicate names.
Related errors
- username_not_normalized
- {client_name} already exists
- user_not_found
- User is not active
- System generated users cannot have refresh tokens connected
AI-assisted analysis of home-assistant/core@58a3fdb3ea (2026-08-14).
Data as JSON: /api/errors/2dc53bc23fb26b09.
Report an issue: GitHub.