xtekky/gpt4free · error · RuntimeError
Missing tokens in response
Error message
Missing tokens in response
What it means
Google's token endpoint returned HTTP 200 but the JSON was missing access_token or refresh_token. A successful code exchange always returns both (refresh_token because the flow requests offline access), so this indicates an anomalous response: an intercepted or HTML body, or an error-shaped 200.
Source
Thrown at g4f/Provider/needs_auth/GeminiCLI.py:1153
}
async with session.post(
"https://oauth2.googleapis.com/token",
data=token_data,
headers={"Content-Type": "application/x-www-form-urlencoded"},
) as resp:
if not resp.ok:
error_text = await resp.text()
raise RuntimeError(f"Token exchange failed: {error_text}")
token_response = await resp.json()
access_token = token_response.get("access_token")
refresh_token = token_response.get("refresh_token")
expires_in = token_response.get("expires_in", 3600)
if not access_token or not refresh_token:
raise RuntimeError("Missing tokens in response")
# Get user info
email = None
async with session.get(
"https://www.googleapis.com/oauth2/v1/userinfo?alt=json",
headers={"Authorization": f"Bearer {access_token}"},
) as resp:
if resp.ok:
user_info = await resp.json()
email = user_info.get("email")
expires_at = int((start_time + expires_in) * 1000) # milliseconds
return {
"access_token": access_token,
"refresh_token": refresh_token,
"expiry_date": expires_at,
"email": email,View on GitHub (pinned to 973504e177)
Solutions
- Log the raw token_response to inspect what was actually returned
- Retry with a brand-new authorization code from a fresh login attempt
- Check for proxy or captive-portal interference on oauth2.googleapis.com
- Update g4f if the token endpoint contract changed
Defensive patterns
Strategy: try-catch
Try / catch
try:
tokens = await GeminiCLI.exchange_code_for_tokens(code, state)
except RuntimeError as e:
if "Missing tokens in response" in str(e):
# anomalous 200; restart the whole login flow
tokens = await GeminiCLI.login() Prevention
- Log the raw token response when this fires to distinguish interception from API change
- Restart the whole login flow rather than retrying the same code
When it happens
Trigger: token_response.get('access_token') or token_response.get('refresh_token') is falsy after a 200 from oauth2.googleapis.com/token in exchange_code_for_tokens.
Common situations: Proxy or TLS interception replacing the response; an API behavior change; a rare Google-side anomaly.
Related errors
- No access_token in refresh response.
- Missing PKCE verifier in state parameter
- Token exchange failed: {error_text}
- OAuth callback timed out
- No authorization code received
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/569a9cc7fc0718dd.
Report an issue: GitHub.