{"record":{"id":"0ede301baf2b8130","repo":"xtekky/gpt4free","slug":"token-exchange-failed-error-text","errorCode":null,"errorMessage":"Token exchange failed: {error_text}","messagePattern":"Token exchange failed: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"g4f/Provider/needs_auth/Antigravity.py","lineNumber":648,"sourceCode":"                \"client_id\": cls.OAUTH_CLIENT_ID,\n                \"client_secret\": cls.OAUTH_CLIENT_SECRET,\n                \"code\": code,\n                \"grant_type\": \"authorization_code\",\n                \"redirect_uri\": ANTIGRAVITY_REDIRECT_URI,\n                \"code_verifier\": verifier,\n            }\n\n            async with session.post(\n                \"https://oauth2.googleapis.com/token\",\n                data=token_data,\n                headers={\n                    \"Content-Type\": \"application/x-www-form-urlencoded\",\n                    \"User-Agent\": \"google-api-nodejs-client/10.3.0\",\n                },\n            ) as resp:\n                if not resp.ok:\n                    error_text = await resp.text()\n                    raise RuntimeError(f\"Token exchange failed: {error_text}\")\n\n                token_response = await resp.json()\n\n            access_token = token_response.get(\"access_token\")\n            refresh_token = token_response.get(\"refresh_token\")\n            expires_in = token_response.get(\"expires_in\", 3600)\n\n            if not access_token or not refresh_token:\n                raise RuntimeError(\"Missing tokens in response\")\n\n            # Get user info\n            email = None\n            async with session.get(\n                \"https://www.googleapis.com/oauth2/v1/userinfo?alt=json\",\n                headers={\"Authorization\": f\"Bearer {access_token}\"},\n            ) as resp:\n                if resp.ok:\n                    user_info = await resp.json()","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/Provider/needs_auth/Antigravity.py#L630-L666","documentation":"The authorization-code-for-token exchange POST to https://oauth2.googleapis.com/token returned a non-ok status. The raw Google error body (JSON with error/error_description such as 'invalid_grant', 'redirect_uri_mismatch', 'invalid_client') is embedded in the message.","triggerScenarios":"POST with grant_type=authorization_code, code, redirect_uri=ANTIGRAVITY_REDIRECT_URI, code_verifier. Fails with: expired or already-used authorization code (codes are single-use and ~10 min TTL), redirect_uri mismatch against the Google OAuth app config, wrong PKCE verifier, or bad client_id/client_secret.","commonSituations":"User took too long between opening the auth URL and completing consent; the callback fired twice and the code was consumed; the redirect URI recorded in Google's console differs from ANTIGRAVITY_REDIRECT_URI; retrying the exchange after a network error reused the same code.","solutions":["Parse error_text: 'invalid_grant' -> code expired/used; restart the login flow for a fresh code. 'redirect_uri_mismatch' -> ensure the exact ANTIGRAVITY_REDIRECT_URI (localhost callback) is used and not rewritten by a proxy.","Do not retry the exchange with the same code; authorization codes are single-use.","Complete the browser consent promptly after generating the auth URL.","Ensure no browser extension or proxy strips the state/code query parameters from the localhost redirect."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    tokens = await Antigravity.exchange_code_for_tokens(code, state)\nexcept RuntimeError as e:\n    if \"Token exchange failed\" in str(e):\n        # do NOT reuse `code`; generate a new authorization URL and retry once\n        raise","preventionTips":["Exchange the authorization code immediately after the callback — codes expire in minutes and are single-use","Never retry an exchange with the same code after any error","Keep redirect_uri identical between the authorization request and the exchange"],"tags":["oauth","google","authorization-code","antigravity"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}