{"record":{"id":"5497cd21cdc6ea9e","repo":"googleworkspace/cli","slug":"failed-to-fetch-user-profile-e","errorCode":null,"errorMessage":"Failed to fetch user profile: {e}","messagePattern":"Failed to fetch user profile: (.+?)","errorType":"exception","errorClass":"GwsError","httpStatus":null,"severity":"error","filePath":"crates/google-workspace-cli/src/helpers/gmail/reply.rs","lineNumber":184,"sourceCode":"    pub extra_to: Option<Vec<Mailbox>>,\n    pub cc: Option<Vec<Mailbox>>,\n    pub bcc: Option<Vec<Mailbox>>,\n    pub remove: Option<Vec<Mailbox>>,\n    pub html: bool,\n    pub attachments: Vec<Attachment>,\n}\n\n/// Fetch the authenticated user's primary email from the Gmail profile API.\n/// Used in reply-all for self-dedup (excluding the user from recipients) and\n/// self-reply detection (switching to original-To-based addressing).\nasync fn fetch_user_email(client: &reqwest::Client, token: &str) -> Result<String, GwsError> {\n    let resp = crate::client::send_with_retry(|| {\n        client\n            .get(\"https://gmail.googleapis.com/gmail/v1/users/me/profile\")\n            .bearer_auth(token)\n    })\n    .await\n    .map_err(|e| GwsError::Other(anyhow::anyhow!(\"Failed to fetch user profile: {e}\")))?;\n\n    if !resp.status().is_success() {\n        let status = resp.status().as_u16();\n        let body = resp\n            .text()\n            .await\n            .unwrap_or_else(|_| \"(error body unreadable)\".to_string());\n        return Err(super::build_api_error(\n            status,\n            &body,\n            \"Failed to fetch user profile\",\n        ));\n    }\n\n    let profile: Value = resp\n        .json()\n        .await\n        .map_err(|e| GwsError::Other(anyhow::anyhow!(\"Failed to parse profile: {e}\")))?;","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/googleworkspace/cli/blob/a3768d0e82ad83cca2da97724e46bea4ff0e6dbd/crates/google-workspace-cli/src/helpers/gmail/reply.rs#L166-L202","documentation":"Transport failure in `fetch_user_email` (reply.rs): `send_with_retry` could not complete `GET https://gmail.googleapis.com/gmail/v1/users/me/profile`, which `+reply-all` uses for self-dedup of recipients and self-reply detection. HTTP failures (401/403) go through `build_api_error`; this branch means no HTTP response at all after retries.","triggerScenarios":"Running `gws gmail +reply-all` offline; DNS/proxy failure to gmail.googleapis.com; connection resets persisting across the whole retry budget.","commonSituations":"Same network-class issues as other gmail helper calls, but noticed specifically during reply-all because that is the only flow that fetches the profile.","solutions":["Restore connectivity and re-run the reply — no mail is sent until the final send call, so retry is safe.","Verify `curl https://gmail.googleapis.com/` connects from the same shell (proxy env vars included).","If behind an allowlisted firewall, keep gmail.googleapis.com on the list.","Enable debug logs to see the underlying reqwest error kind."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// fetch_user_email only fails fatally at transport level; retry with backoff before giving up on reply-all\nlet email = match fetch_user_email(client, token).await {\n    Ok(e) => e,\n    Err(GwsError::Other(e)) if e.to_string().contains(\"Failed to fetch user profile\") => {\n        tokio::time::sleep(Duration::from_secs(2)).await;\n        fetch_user_email(client, token).await?\n    }\n    Err(e) => return Err(e),\n};","preventionTips":["Reply-all makes one extra profile call — ensure gmail.googleapis.com is reachable before scripting it.","No mail is sent before the final send call, so retrying the whole command is always safe.","Distinguish transport (this) from auth (GwsError::Api with 401/403) failures when scripting exit-code handling."],"tags":["gmail","profile","network","reqwest","reply-all"],"backgroundTag":"http-request-failed","analyzedSha":"a3768d0e82ad83cca2da97724e46bea4ff0e6dbd","analyzedAt":"2026-08-16T19:51:46.516Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}