xtekky/gpt4free · error · TokenManagerError

NO_REFRESH_TOKEN

NO_REFRESH_TOKEN

Error message

No refresh token

What it means

TokenManagerError NO_REFRESH_TOKEN raised at the top of SharedTokenManager.performTokenRefresh (sharedTokenManager.py:178): after loading credentials into the client, the stored credentials have no 'refresh_token', so a refresh is impossible. Unlike error 247 this fires inside the shared manager's coordinated refresh path and is typed, letting callers distinguish 'must re-auth' from generic failures.

Source

Thrown at g4f/Provider/qwen/sharedTokenManager.py:178

            if field not in data or not isinstance(data[field], str):
                raise ValueError(f"Invalid credentials: missing {field}")
        if "expiry_date" not in data or not isinstance(
            data["expiry_date"], (int, float)
        ):
            raise ValueError("Invalid credentials: missing expiry_date")
        return data

    async def performTokenRefresh(
        self, qwen_client: IQwenOAuth2Client, force_refresh: bool
    ):
        lock_path = self.getLockFilePath()
        try:
            if self.memory_cache["credentials"] is None:
                self.reloadCredentialsFromFile()
            qwen_client.setCredentials(self.memory_cache["credentials"])
            current_credentials = qwen_client.getCredentials()
            if not current_credentials.get("refresh_token"):
                raise TokenManagerError(TokenError.NO_REFRESH_TOKEN, "No refresh token")
            await self.acquireLock(lock_path)

            self.checkAndReloadIfNeeded()

            if (
                not force_refresh
                and self.memory_cache["credentials"]
                and self.isTokenValid(self.memory_cache["credentials"])
            ):
                qwen_client.setCredentials(self.memory_cache["credentials"])
                return self.memory_cache["credentials"]

            response = await qwen_client.refreshAccessToken()
            if not response or isErrorResponse(response):
                raise TokenManagerError(TokenError.REFRESH_FAILED, str(response))
            token_data = response
            if "access_token" not in token_data:
                raise TokenManagerError(

View on GitHub (pinned to 973504e177)

Solutions

  1. Re-run the Qwen device authorization flow to mint a full credential set
  2. Inspect the credentials file and add/repair the refresh_token field if you have a valid one
  3. Catch TokenManagerError with code NO_REFRESH_TOKEN in callers and route the user to re-login instead of retrying

Example fix

// before
creds = await manager.getValidCredentials(client)  # raises NO_REFRESH_TOKEN

// after
from g4f.Provider.qwen.sharedTokenManager import TokenManagerError, TokenError
try:
    creds = await manager.getValidCredentials(client)
except TokenManagerError as e:
    if e.error == TokenError.NO_REFRESH_TOKEN:
        await start_device_login()  # re-auth instead of retry
    else:
        raise
Defensive patterns

Strategy: validation

Validate before calling

creds = manager.memory_cache.get("credentials")
if creds is None or not creds.get("refresh_token"):
    await start_qwen_device_login()  # nothing to refresh; authenticate first
creds = await manager.getValidCredentials(qwen_client)

Type guard

def has_refresh_token(creds) -> bool:
    return isinstance(creds, dict) and isinstance(creds.get("refresh_token"), str) and bool(creds["refresh_token"])

Try / catch

from g4f.Provider.qwen.sharedTokenManager import TokenManagerError
try:
    creds = await manager.getValidCredentials(qwen_client)
except TokenManagerError as e:
    if getattr(e, "error", None) is not None and "NO_REFRESH_TOKEN" in str(e.error):
        await start_qwen_device_login()  # typed signal: re-auth, never retry
    else:
        raise

Prevention

When it happens

Trigger: getValidCredentials() triggers performTokenRefresh while the loaded credentials dict lacks refresh_token — after a prior expiry wiped it, on a first run with a partially populated file, or after failed validation left None credentials reloaded from a sparse file.

Common situations: Post-expiry state where qwenOAuth2 reset credentials; credentials file created by an older g4f that didn't persist refresh_token; manual token extraction that copied only the access token.

Related errors


AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14). Data as JSON: /api/errors/080c116f1d16a377. Report an issue: GitHub.