xtekky/gpt4free · critical · RuntimeError

Token refresh failed: {text}

Error message

Token refresh failed: {text}

What it means

Thrown when the Google OAuth token-refresh POST to OAUTH_REFRESH_URL (oauth2.googleapis.com/token) returns a non-200 status. The provider wraps the raw HTTP response body in the message, so the body usually contains Google's OAuth error (e.g. 'invalid_grant', 'invalid_client'). It means the stored credentials could not be exchanged for a new access token.

Source

Thrown at g4f/Provider/needs_auth/Antigravity.py:457

        await self._refresh_and_cache_token(refresh_token)

    async def _refresh_and_cache_token(self, refresh_token: str) -> None:
        """Refresh the OAuth token and cache it."""
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        data = {
            "client_id": self.OAUTH_CLIENT_ID,
            "client_secret": self.OAUTH_CLIENT_SECRET,
            "refresh_token": refresh_token,
            "grant_type": "refresh_token",
        }

        async with aiohttp.ClientSession() as session:
            async with session.post(
                self.OAUTH_REFRESH_URL, data=data, headers=headers
            ) as resp:
                if resp.status != 200:
                    text = await resp.text()
                    raise RuntimeError(f"Token refresh failed: {text}")
                resp_data = await resp.json()
                access_token = resp_data.get("access_token")
                expires_in = resp_data.get("expires_in", 3600)  # seconds

                if not access_token:
                    raise RuntimeError("No access_token in refresh response.")

                self._access_token = access_token
                self._expiry = time.time() + expires_in

                expiry_date_ms = int(self._expiry * 1000)  # milliseconds
                await self._cache_token(access_token, expiry_date_ms)

    async def _cache_token(self, access_token: str, expiry_date: int) -> None:
        """Cache token in memory."""
        token_data = {
            "access_token": access_token,
            "expiry_date": expiry_date,

View on GitHub (pinned to 973504e177)

Solutions

  1. Read the response body embedded in the message: 'invalid_grant' means re-authenticate (delete the cached Antigravity credentials file and run the login flow again); 'invalid_client' means the baked-in client credentials are wrong for this provider version.
  2. Delete the cached token/credentials file so initialize_auth() forces a fresh interactive login instead of refreshing.
  3. Verify system clock skew is not causing JWT/grant failures (NTP sync).
  4. Upgrade g4f to the latest version in case the provider's OAuth client credentials were rotated upstream.

Example fix

# before: stale credentials keep failing refresh
# (delete cached credentials so the next call re-authenticates)
rm ~/.config/g4f/antigravity_credentials.json  # adjust path to your cache location

# after: re-run the provider login flow
python -c "import asyncio; from g4f.Provider.needs_auth import Antigravity; asyncio.run(Antigravity.login())"
Defensive patterns

Strategy: try-catch

Try / catch

try:
    await antigravity.create_async_generator(...)
except RuntimeError as e:
    if "Token refresh failed" in str(e):
        # credentials are dead: purge cache and re-authenticate
        await antigravity.login()

Prevention

When it happens

Trigger: POST to https://oauth2.googleapis.com/token with grant_type=refresh_token returns status != 200. Typical causes: the refresh_token was revoked or expired (invalid_grant), the OAUTH_CLIENT_ID/OAUTH_CLIENT_SECRET pair is wrong (invalid_client), or the token was issued for a different client.

Common situations: Stored credentials JSON is stale after the user revoked access in their Google account settings; client secret rotated on the Google side; user re-ran login over an old credentials file; long-running process whose refresh token exceeded Google's 6-month inactivity expiry.

Related errors


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