home-assistant/core · error · ValueError

System generated users cannot have refresh tokens connected

Error message

System generated users cannot have refresh tokens connected to a client.

What it means

Thrown by AuthManager.async_create_refresh_token (homeassistant/auth/__init__.py:466) when a system-generated user is given a client_id. System-generated users may only hold system-type refresh tokens, which by definition are not bound to an OAuth client.

Source

Thrown at homeassistant/auth/__init__.py:466

                modules[module_id] = module.name
        return modules

    async def async_create_refresh_token(
        self,
        user: models.User,
        client_id: str | None = None,
        client_name: str | None = None,
        client_icon: str | None = None,
        token_type: str | None = None,
        access_token_expiration: timedelta = ACCESS_TOKEN_EXPIRATION,
        credential: models.Credentials | None = None,
    ) -> models.RefreshToken:
        """Create a new refresh token for a user."""
        if not user.is_active:
            raise ValueError("User is not active")

        if user.system_generated and client_id is not None:
            raise ValueError(
                "System generated users cannot have refresh tokens connected "
                "to a client."
            )

        if token_type is None:
            if user.system_generated:
                token_type = models.TOKEN_TYPE_SYSTEM
            else:
                token_type = models.TOKEN_TYPE_NORMAL

        if token_type is models.TOKEN_TYPE_NORMAL:
            expire_at = time.time() + REFRESH_TOKEN_EXPIRATION
        else:
            expire_at = None

        if user.system_generated != (token_type == models.TOKEN_TYPE_SYSTEM):
            raise ValueError(
                "System generated users can only have system type refresh tokens"

View on GitHub (pinned to 58a3fdb3ea)

Solutions

  1. Pass client_id=None for system-generated users
  2. Branch the call: system users get no client metadata, human users get client_id from the auth flow

Example fix

// before
await hass.auth.async_create_refresh_token(system_user, client_id=client_id)

# after
await hass.auth.async_create_refresh_token(
    system_user,
    client_id=None if system_user.system_generated else client_id,
)
Defensive patterns

Strategy: validation

Validate before calling

if user.system_generated:
    assert client_id is None
await hass.auth.async_create_refresh_token(user, client_id=client_id)

Type guard

def valid_client_binding(user, client_id) -> bool:
    return client_id is None or not user.system_generated

Prevention

When it happens

Trigger: Calling async_create_refresh_token(system_user, client_id="http://x") — any non-None client_id for a user with system_generated=True.

Common situations: Generic token-issuing code paths that always pass a client_id; frontend code reusing the user token flow for integration/service accounts.

Related errors


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