{"record":{"id":"4a7562f4dab4fae9","repo":"router-for-me/CLIProxyAPI","slug":"antigravity-userinfo-response-missing-email","errorCode":null,"errorMessage":"antigravity userinfo: response missing email","messagePattern":"antigravity userinfo: response missing email","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/antigravity/auth.go","lineNumber":221,"sourceCode":"\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 \"\", fmt.Errorf(\"antigravity userinfo: read response: %w\", errRead)\n\t\t}\n\t\tbody := strings.TrimSpace(string(bodyBytes))\n\t\tif body == \"\" {\n\t\t\treturn \"\", fmt.Errorf(\"antigravity userinfo: request failed: status %d\", resp.StatusCode)\n\t\t}\n\t\treturn \"\", fmt.Errorf(\"antigravity userinfo: request failed: status %d: %s\", resp.StatusCode, body)\n\t}\n\tvar info userInfo\n\tif errDecode := json.NewDecoder(resp.Body).Decode(&info); errDecode != nil {\n\t\treturn \"\", fmt.Errorf(\"antigravity userinfo: decode response: %w\", errDecode)\n\t}\n\temail := strings.TrimSpace(info.Email)\n\tif email == \"\" {\n\t\treturn \"\", fmt.Errorf(\"antigravity userinfo: response missing email\")\n\t}\n\treturn email, nil\n}\n\n// FetchProjectID retrieves the project ID for the authenticated user via loadCodeAssist\nfunc (o *AntigravityAuth) FetchProjectID(ctx context.Context, accessToken string) (string, error) {\n\tuserAgent := o.shortUserAgent()\n\tloadReqBody := map[string]any{\n\t\t\"metadata\": antigravityLoadCodeAssistMetadata(),\n\t}\n\n\trawBody, errMarshal := json.Marshal(loadReqBody)\n\tif errMarshal != nil {\n\t\treturn \"\", fmt.Errorf(\"marshal request body: %w\", errMarshal)\n\t}\n\n\tendpointURL := fmt.Sprintf(\"%s/%s:loadCodeAssist\", APIEndpoint, APIVersion)\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, endpointURL, strings.NewReader(string(rawBody)))","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/antigravity/auth.go#L203-L239","documentation":"Userinfo responded 2xx with decodable JSON, but the email field was absent or whitespace-only. The account may not have an email exposed to this OAuth client (scope not granted), or the response schema put the address under a different key.","triggerScenarios":"Authorization request lacked the email scope, so Google omits the email field; Workspace accounts with hidden emails; schema change renaming the field.","commonSituations":"Authorization URL built without email scope; consent screen skipping email grant; service-account-style flows that have no primary email.","solutions":["Add the email scope to the Antigravity authorization request and re-authorize","Inspect the decoded userinfo JSON for where the address actually appears (e.g. emails array) and map accordingly","Fall back to another identifier if email is unavailable for that account type"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"response missing email\") {\n\t// re-authorize with email scope or use an alternate account identifier\n}","preventionTips":["Request the email scope during authorization","Map alternate fields (e.g. emails array) when accounts hide the primary email"],"tags":["oauth","antigravity","user-info","scopes"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}