home-assistant/core · error · ValueError
Credential is already linked to a user
Error message
Credential is already linked to a user
What it means
ConfigEntryNotReady is Home Assistant's signal that a config entry could not be set up because a dependency (here the Bosch Smart Home Controller) was unreachable. In bosch_shc it is raised from SHCConnectionError while constructing the SHCSession, telling the config entry machinery to retry setup later instead of failing permanently. The coordinator pattern keeps the entry in a 'setup in progress/retry' state with exponential backoff.
Source
Thrown at homeassistant/auth/__init__.py:341
name=info.name,
is_active=info.is_active,
group_ids=[GROUP_ID_ADMIN if info.group is None else info.group],
local_only=info.local_only,
)
self.hass.bus.async_fire(EVENT_USER_ADDED, {"user_id": user.id})
return user
async def async_link_user(
self, user: models.User, credentials: models.Credentials
) -> None:
"""Link credentials to an existing user."""
linked_user = await self.async_get_user_by_credentials(credentials)
if linked_user == user:
return
if linked_user is not None:
raise ValueError("Credential is already linked to a user")
await self._store.async_link_user(user, credentials)
async def async_remove_user(self, user: models.User) -> None:
"""Remove a user."""
tasks = [
self.async_remove_credentials(credentials)
for credentials in user.credentials
]
if tasks:
await asyncio.gather(*tasks)
await self._store.async_remove_user(user)
self.hass.bus.async_fire(EVENT_USER_REMOVED, {"user_id": user.id})
async def async_update_user(View on GitHub (pinned to 58a3fdb3ea)
Solutions
- Verify the Bosch Smart Home Controller is powered on and reachable: ping the host / open https://<host>:8444 in a browser from the same machine running HA.
- Check the configured host in the config entry still matches the controller's current IP (or relies on freshly discovered zeroconf info); re-run discovery or update the host.
- Confirm the SSL certificate and key files referenced by CONF_SSL_CERTIFICATE/CONF_SSL_KEY still exist and match the controller's current cert (re-pair via the Bosch app if needed).
- If the error persists, enable debug logging for bosch_shc and check the underlying SHCConnectionError message; HA will keep retrying with backoff, so a transient outage self-heals once connectivity returns.
Example fix
// No code fix — this is a setup-time connectivity signal. But ensure transient
// errors surface as NotReady rather than a hard failure:
try:
session = await hass.async_add_executor_job(
SHCSession, data[CONF_HOST], data[CONF_SSL_CERTIFICATE],
data[CONF_SSL_KEY], False, zeroconf,
)
except SHCConnectionError as err:
raise ConfigEntryNotReady from err # HA retries setup automatically
// If you control the caller and the host may change, refresh it first:
// entry.async_update_hass_config(hass, {**entry.data, CONF_HOST: new_ip}) Defensive patterns
Strategy: retry
Validate before calling
# Before setup, probe reachability of the controller
import socket, ssl
def host_reachable(host: str, port: int = 8444, timeout: float = 3.0) -> bool:
try:
with socket.create_connection((host, port), timeout=timeout):
return True
except OSError:
return False Type guard
# Not applicable — Python duck-typed integration; guard on exception type instead assert isinstance(err, SHCConnectionError) # narrow before converting to ConfigEntryNotReady
Try / catch
try:
session = await hass.async_add_executor_job(SHCSession, host, cert, key, False, zeroconf)
except SHCAuthenticationError as err:
raise ConfigEntryAuthFailed from err # credential problem -> reauth
except SHCConnectionError as err:
raise ConfigEntryNotReady from err # transient -> retry with backoff Prevention
- Use a DHCP reservation or mDNS/zeroconf-discovered host so the controller IP never drifts.
- Keep the pairing certificate and key files backed up; a mismatch after re-pairing causes persistent connection failures.
- Watch for the 'UPDATE_AVAILABLE' warning in the source — update the controller via the Bosch app before debugging connectivity.
- Alert on repeated ConfigEntryNotReady retries rather than ignoring them; sustained retries mean a real outage, not transient flakiness.
When it happens
Trigger: Creating an SHCSession (hass.async_add_executor_job(SHCSession, host, ssl_cert, ssl_key, False, zeroconf)) throws SHCConnectionError — the HTTP/WebSocket connection to the Bosch SHC box at data[CONF_HOST] cannot be established (device offline, wrong IP, TLS handshake failure, or mDNS/zeroconf info stale).
Common situations: Controller powered off or rebooting (e.g. after a firmware update), router DHCP changed the SHC IP while the config still pins the old host, self-signed certificate/key mismatch after re-pairing, or firewall/VLAN blocking port 8444/8084 to the controller.
Related errors
- Could not connect to Autoskope API
- cannot_connect
- Unable find multi-factor auth module: {mfa_module_id}
- System generated users cannot disable multi-factor auth modu
- Unable to connect to Abode: {ex}
AI-assisted analysis of home-assistant/core@58a3fdb3ea (2026-08-14).
Data as JSON: /api/errors/129a41399caea23a.
Report an issue: GitHub.