xtekky/gpt4free · critical · Exception
Refresh token expired or invalid
Error message
Refresh token expired or invalid
What it means
Raised by QwenOAuth2.refreshAccessToken (qwenOAuth2.py:177) when the token endpoint returns HTTP 400 during a refresh_token grant — the OAuth-standard signal that the refresh token is expired, revoked, or invalid. Crucially, the handler first resets self.credentials to an empty QwenCredentials(), so the stored session is destroyed and interactive re-authentication is required.
Source
Thrown at g4f/Provider/qwen/qwenOAuth2.py:177
"grant_type": "refresh_token",
"refresh_token": self.credentials["refresh_token"],
"client_id": QWEN_OAUTH_CLIENT_ID,
}
async with aiohttp.ClientSession(headers={"user-agent": ""}) as session:
async with session.post(
QWEN_OAUTH_TOKEN_ENDPOINT,
headers={
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json",
},
data=object_to_urlencoded(body_data),
) as resp:
resp_json = await resp.json()
if resp.status != 200:
if resp.status == 400:
# Handle token expiration
self.credentials = QwenCredentials()
raise Exception("Refresh token expired or invalid")
raise Exception(f"Token refresh failed {resp.status}: {resp_json}")
return resp_json
def isTokenValid(self, credentials: QwenCredentials) -> bool:
if not credentials.get("expiry_date"):
return False
return time.time() * 1000 < credentials["expiry_date"] - TOKEN_REFRESH_BUFFER_MS
View on GitHub (pinned to 973504e177)
Solutions
- Re-run the Qwen device authorization flow — the wiped credentials cannot be recovered
- Prevent concurrent refreshes (the shared token manager's file lock exists for this; ensure a single instance refreshes)
- Refresh proactively before expiry rather than after, so tokens rotate cleanly
- If single-use refresh tokens are the norm, persist the new refresh_token immediately after each refresh
Defensive patterns
Strategy: fallback
Try / catch
try:
resp = await qwen_client.refreshAccessToken()
except Exception as exc:
if "Refresh token expired or invalid" in str(exc):
# credentials were wiped; interactive re-auth is the only path
await start_qwen_device_login()
else:
raise Prevention
- Refresh tokens before they expire rather than after
- Serialize refreshes across processes to protect rotating refresh tokens
- Detect this error early and route users to re-login instead of retry loops
When it happens
Trigger: POST to QWEN_OAUTH_TOKEN_ENDPOINT with grant_type=refresh_token returns 400: refresh token past its lifetime, revoked server-side (password change / logout all devices), or single-use token already consumed by a concurrent process.
Common situations: Credentials stored long ago and Qwen's refresh-token TTL elapsed; two g4f processes raced and one consumed the rotating refresh token; account security event revoked grants.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- No refresh token
- Missing tokens in response
- No valid access token obtained.
- Device authorization failed {resp.status}: {resp_json}
- Device authorization error: {resp_json.get('error')} - {resp
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/5ad7db3ddda3ddc9.
Report an issue: GitHub.