{"record":{"id":"868238f14c63f99e","repo":"router-for-me/CLIProxyAPI","slug":"antigravity-token-exchange-request-failed-status","errorCode":null,"errorMessage":"antigravity token exchange: request failed: status %d","messagePattern":"antigravity token exchange: request failed: status (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/antigravity/auth.go","lineNumber":169,"sourceCode":"\n\tresp, errDo := o.httpClient.Do(req)\n\tif errDo != nil {\n\t\treturn nil, fmt.Errorf(\"antigravity token exchange: execute request: %w\", errDo)\n\t}\n\tdefer func() {\n\t\tif errClose := resp.Body.Close(); errClose != nil {\n\t\t\tlog.Errorf(\"antigravity token exchange: close body error: %v\", errClose)\n\t\t}\n\t}()\n\n\tif resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {\n\t\tbodyBytes, errRead := io.ReadAll(io.LimitReader(resp.Body, 8<<10))\n\t\tif errRead != nil {\n\t\t\treturn nil, fmt.Errorf(\"antigravity token exchange: read response: %w\", errRead)\n\t\t}\n\t\tbody := strings.TrimSpace(string(bodyBytes))\n\t\tif body == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"antigravity token exchange: request failed: status %d\", resp.StatusCode)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"antigravity token exchange: request failed: status %d: %s\", resp.StatusCode, body)\n\t}\n\n\tvar token TokenResponse\n\tif errDecode := json.NewDecoder(resp.Body).Decode(&token); errDecode != nil {\n\t\treturn nil, fmt.Errorf(\"antigravity token exchange: decode response: %w\", errDecode)\n\t}\n\treturn &token, nil\n}\n\n// FetchUserInfo retrieves user email from Google\nfunc (o *AntigravityAuth) FetchUserInfo(ctx context.Context, accessToken string) (string, error) {\n\taccessToken = strings.TrimSpace(accessToken)\n\tif accessToken == \"\" {\n\t\treturn \"\", fmt.Errorf(\"antigravity userinfo: missing access token\")\n\t}\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, UserInfoEndpoint, nil)","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/antigravity/auth.go#L151-L187","documentation":"The Antigravity token exchange endpoint answered with a non-2xx status and an empty body, so only the status code can be reported. Common statuses: 400 (invalid/expired/reused authorization code, redirect_uri mismatch, bad client_id/secret), 401, 403, or a 5xx from Google's OAuth service.","triggerScenarios":"Exchanging an authorization code that expired (~10 min lifetime) or was already used once; redirect_uri not matching the one in the authorize request; wrong client_id/client_secret constants; Google OAuth outage returning 503 with empty body.","commonSituations":"Re-running the OAuth callback manually with a stale code; clock skew plus code expiry; the app registered redirect URI differing (port/path) from redirectURI passed in.","solutions":["Restart the full OAuth flow to get a fresh authorization code and exchange it immediately","Verify redirectURI passed to ExchangeCodeForTokens matches exactly the redirect used in the authorize URL (scheme, host, port, path)","Confirm ClientID/ClientSecret constants are current for the Antigravity app","If 5xx persists, check the Google OAuth status page and retry later"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if time.Since(codeIssuedAt) > 5*time.Minute {\n\t// code near its ~10min lifetime — get a new one before exchanging\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"token exchange: request failed: status 400\") {\n\t// restart OAuth flow: code expired, used, or redirect mismatch\n}","preventionTips":["Exchange the authorization code immediately after the callback","Ensure redirectURI matches the authorize request exactly","Never replay an already-exchanged code"],"tags":["oauth","antigravity","http-status","authorization-code"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}