xtekky/gpt4free · error · Exception
No refresh token
Error message
No refresh token
What it means
Raised by QwenOAuth2.refreshAccessToken (qwenOAuth2.py:157) when refresh is attempted while the stored credentials contain no refresh_token. It is a pure precondition failure: the client was asked to refresh an authorization it never had (or no longer has).
Source
Thrown at g4f/Provider/qwen/qwenOAuth2.py:157
"Accept": "application/json",
},
data=object_to_urlencoded(body_data),
) as resp:
resp_json = await resp.json()
if resp.status != 200:
# Check for OAuth RFC 8628 responses
if resp.status == 400:
if "error" in resp_json:
if resp_json["error"] == "authorization_pending":
return {"status": "pending"}
if resp_json["error"] == "slow_down":
return {"status": "pending", "slowDown": True}
raise Exception(f"Token poll failed {resp.status}: {resp_json}")
return resp_json
async def refreshAccessToken(self) -> Union[Dict, ErrorDataDict]:
if not self.credentials.get("refresh_token"):
raise Exception("No refresh token")
body_data = {
"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 expirationView on GitHub (pinned to 973504e177)
Solutions
- Re-run the Qwen device authorization flow to obtain fresh tokens
- Check credentials storage: ensure 'refresh_token' is present before enabling Qwen
- Guard callers with an upfront check for refresh_token before requesting a refresh
Example fix
// before
resp = await qwen_client.refreshAccessToken() # may raise No refresh token
// after
creds = qwen_client.getCredentials()
if not creds.get("refresh_token"):
raise RuntimeError("re-authentication required")
resp = await qwen_client.refreshAccessToken() Defensive patterns
Strategy: validation
Validate before calling
creds = qwen_client.getCredentials()
assert creds.get("refresh_token"), "cannot refresh without a refresh token"
resp = await qwen_client.refreshAccessToken() Type guard
def can_refresh(creds: dict) -> bool:
return isinstance(creds, dict) and isinstance(creds.get("refresh_token"), str) and len(creds["refresh_token"]) > 0 Try / catch
try:
resp = await qwen_client.refreshAccessToken()
except Exception as exc:
if "No refresh token" in str(exc):
await start_qwen_device_login()
else:
raise Prevention
- Check for refresh_token before calling refresh — it is a precondition, not a runtime surprise
- Persist complete credential sets (access, refresh, token_type, expiry)
- Re-authenticate promptly after expiry wipes credentials
When it happens
Trigger: Calling refreshAccessToken() (directly or via the token manager) after setCredentials() with a dict lacking 'refresh_token' — e.g. after qwenOAuth2.py:177 reset credentials to empty QwenCredentials() on a prior 400.
Common situations: Refresh token previously expired and credentials were wiped, then another refresh is attempted; credentials file hand-created with only an access_token; race where two processes refresh concurrently and one clears state.
Related errors
- Refresh token expired or invalid
- device_code is required for polling
- Device authorization error: {resp_json.get('error')} - {resp
- Missing tokens in response
- No valid access token obtained.
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/c7d463d2235e0b07.
Report an issue: GitHub.