{"record":{"id":"afb020e89a0c7a6c","repo":"xtekky/gpt4free","slug":"token-exchange-failed-error-text-afb020","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/GeminiCLI.py","lineNumber":1144,"sourceCode":"\n        async with aiohttp.ClientSession() as session:\n            token_data = {\n                \"client_id\": AuthManager.OAUTH_CLIENT_ID,\n                \"client_secret\": AuthManager.OAUTH_CLIENT_SECRET,\n                \"code\": code,\n                \"grant_type\": \"authorization_code\",\n                \"redirect_uri\": GEMINICLI_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={\"Content-Type\": \"application/x-www-form-urlencoded\"},\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":1126,"sourceCodeEnd":1162,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/Provider/needs_auth/GeminiCLI.py#L1126-L1162","documentation":"The POST to https://oauth2.googleapis.com/token exchanging the authorization code returned a non-OK status; the error body is embedded. Common bodies: invalid_grant (code already used or expired — codes are single-use and live roughly 10 minutes), mismatching code_verifier, or redirect_uri mismatch with GEMINICLI_REDIRECT_URI.","triggerScenarios":"Exchanging an authorization code that was already consumed once, pasted a second time, or older than its short validity; PKCE verifier from the state does not match the challenge sent at authorization; redirect_uri differs between the auth request and token request.","commonSituations":"Browser pre-fetch or middleware consumes the code via the localhost callback before the manual path uses it; retrying after a failure with the same code; clock drift; copy/paste truncation of the code.","solutions":["Start a fresh login attempt to get a new authorization code — codes are single-use","Ensure the exact same redirect URI is used in both steps (use the built-in callback server, not a hand-edited URL)","Check the embedded body: invalid_grant means stale code; mismatch means PKCE or redirect mismatch","Complete the exchange promptly (codes expire in minutes)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    tokens = await GeminiCLI.exchange_code_for_tokens(code, state)\nexcept RuntimeError as e:\n    msg = str(e)\n    if \"Token exchange failed\" in msg and \"invalid_grant\" in msg:\n        # code consumed or expired: only a fresh code helps\n        raise AuthRestart(\"restart login to get a new authorization code\")\n    raise","preventionTips":["Exchange the code immediately after consent; codes are single-use and short-lived","Never replay a code after a partial failure — restart the flow","Use the built-in localhost callback so the code is captured exactly once"],"tags":["oauth","gemini","login","token-exchange","http"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}