home-assistant/core · error · ValueError

System generated users can only have system type refresh tok

Error message

System generated users can only have system type refresh tokens

What it means

Thrown by AuthManager.async_create_refresh_token (homeassistant/auth/__init__.py:483) when the system_generated flag of the user does not match the requested token type: system-generated users must get TOKEN_TYPE_SYSTEM, and only system-generated users may get TOKEN_TYPE_SYSTEM. Normal users requesting system tokens (or system users requesting normal/long-lived tokens without the default resolution) violate this.

Source

Thrown at homeassistant/auth/__init__.py:483

        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"
            )

        if token_type == models.TOKEN_TYPE_NORMAL and client_id is None:
            raise ValueError("Client is required to generate a refresh token.")

        if (
            token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN
            and client_name is None
        ):
            raise ValueError("Client_name is required for long-lived access token")

        if token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN:
            for token in user.refresh_tokens.values():
                if (
                    token.client_name == client_name
                    and token.token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN
                ):

View on GitHub (pinned to 58a3fdb3ea)

Solutions

  1. For normal users, omit token_type (defaults to TOKEN_TYPE_NORMAL) or use TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN with a client_name
  2. Never pass TOKEN_TYPE_SYSTEM yourself — it is reserved for system-generated users and defaults correctly when token_type is None

Example fix

// before
await hass.auth.async_create_refresh_token(user, token_type=models.TOKEN_TYPE_SYSTEM)  # user is not system-generated

# after
await hass.auth.async_create_refresh_token(user, client_id=client_id)  # token_type omitted
Defensive patterns

Strategy: validation

Validate before calling

if not user.system_generated:
    assert token_type is not models.TOKEN_TYPE_SYSTEM
await hass.auth.async_create_refresh_token(user, client_id, token_type=token_type)

Type guard

def token_type_matches(user, token_type) -> bool:
    return user.system_generated == (token_type == models.TOKEN_TYPE_SYSTEM)

Prevention

When it happens

Trigger: Calling async_create_refresh_token(user, token_type=models.TOKEN_TYPE_SYSTEM) for a regular user; passing token_type=models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN for a system-generated user.

Common situations: Copy-pasted token code switching from a service account to a human user without dropping token_type; custom long-lived-token tooling applied to system users.

Related errors


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