{"record":{"id":"944758c587c22154","repo":"xtekky/gpt4free","slug":"token-refresh-failed-text","errorCode":null,"errorMessage":"Token refresh failed: {text}","messagePattern":"Token refresh failed: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"critical","filePath":"g4f/Provider/needs_auth/Antigravity.py","lineNumber":457,"sourceCode":"        await self._refresh_and_cache_token(refresh_token)\n\n    async def _refresh_and_cache_token(self, refresh_token: str) -> None:\n        \"\"\"Refresh the OAuth token and cache it.\"\"\"\n        headers = {\"Content-Type\": \"application/x-www-form-urlencoded\"}\n        data = {\n            \"client_id\": self.OAUTH_CLIENT_ID,\n            \"client_secret\": self.OAUTH_CLIENT_SECRET,\n            \"refresh_token\": refresh_token,\n            \"grant_type\": \"refresh_token\",\n        }\n\n        async with aiohttp.ClientSession() as session:\n            async with session.post(\n                self.OAUTH_REFRESH_URL, data=data, headers=headers\n            ) as resp:\n                if resp.status != 200:\n                    text = await resp.text()\n                    raise RuntimeError(f\"Token refresh failed: {text}\")\n                resp_data = await resp.json()\n                access_token = resp_data.get(\"access_token\")\n                expires_in = resp_data.get(\"expires_in\", 3600)  # seconds\n\n                if not access_token:\n                    raise RuntimeError(\"No access_token in refresh response.\")\n\n                self._access_token = access_token\n                self._expiry = time.time() + expires_in\n\n                expiry_date_ms = int(self._expiry * 1000)  # milliseconds\n                await self._cache_token(access_token, expiry_date_ms)\n\n    async def _cache_token(self, access_token: str, expiry_date: int) -> None:\n        \"\"\"Cache token in memory.\"\"\"\n        token_data = {\n            \"access_token\": access_token,\n            \"expiry_date\": expiry_date,","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/Provider/needs_auth/Antigravity.py#L439-L475","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Delete the cached token/credentials file so initialize_auth() forces a fresh interactive login instead of refreshing.","Verify system clock skew is not causing JWT/grant failures (NTP sync).","Upgrade g4f to the latest version in case the provider's OAuth client credentials were rotated upstream."],"exampleFix":"# before: stale credentials keep failing refresh\n# (delete cached credentials so the next call re-authenticates)\nrm ~/.config/g4f/antigravity_credentials.json  # adjust path to your cache location\n\n# after: re-run the provider login flow\npython -c \"import asyncio; from g4f.Provider.needs_auth import Antigravity; asyncio.run(Antigravity.login())\"","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    await antigravity.create_async_generator(...)\nexcept RuntimeError as e:\n    if \"Token refresh failed\" in str(e):\n        # credentials are dead: purge cache and re-authenticate\n        await antigravity.login()","preventionTips":["Persist the credentials file in stable storage so refresh tokens survive restarts","Refresh tokens proactively before expiry (self._expiry) rather than on failure","Avoid revoking the app in Google account settings unless you intend to re-login"],"tags":["oauth","authentication","google","antigravity","network"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}