home-assistant/core · error · ValueError

Client_name is required for long-lived access token

Error message

Client_name is required for long-lived access token

What it means

Thrown by AuthManager.async_create_refresh_token (homeassistant/auth/__init__.py:494) when creating a TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN without a client_name. Long-lived tokens are surfaced in the UI by name, so the name is required and doubles as the uniqueness key.

Source

Thrown at homeassistant/auth/__init__.py:494

        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
                ):
                    # Each client_name can only have one
                    # long_lived_access_token type of refresh token
                    raise ValueError(f"{client_name} already exists")

        return await self._store.async_create_refresh_token(
            user,
            client_id,
            client_name,
            client_icon,
            token_type,
            access_token_expiration,

View on GitHub (pinned to 58a3fdb3ea)

Solutions

  1. Provide a descriptive client_name, e.g. client_name="My script"
  2. Ensure it is unique among the user's existing long-lived token names to avoid the '{client_name} already exists' error next

Example fix

// before
await hass.auth.async_create_refresh_token(
    user, token_type=models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN
)

# after
await hass.auth.async_create_refresh_token(
    user,
    token_type=models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN,
    client_name="My script",
)
Defensive patterns

Strategy: validation

Validate before calling

if token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN:
    assert client_name
await hass.auth.async_create_refresh_token(
    user, token_type=token_type, client_name=client_name
)

Type guard

def long_lived_ready(token_type, client_name) -> bool:
    return token_type is not models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN or bool(client_name)

Prevention

When it happens

Trigger: Calling async_create_refresh_token(user, token_type=models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN, client_name=None).

Common situations: API wrappers that omit client_name; porting scripts that used only client_id for normal tokens.

Related errors


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