{"record":{"id":"c9af61436882d684","repo":"googleworkspace/cli","slug":"failed-to-list-calendars-e","errorCode":null,"errorMessage":"Failed to list calendars: {e}","messagePattern":"Failed to list calendars: (.+?)","errorType":"exception","errorClass":"GwsError","httpStatus":null,"severity":"error","filePath":"crates/google-workspace-cli/src/helpers/calendar.rs","lineNumber":268,"sourceCode":"        // From now, N days ahead\n        let end = now_in_tz + chrono::Duration::days(days);\n        (now_in_tz, end)\n    };\n\n    let time_min = time_min_dt.to_rfc3339();\n    let time_max = time_max_dt.to_rfc3339();\n\n    // client already built above for timezone resolution\n    let calendar_filter = matches.get_one::<String>(\"calendar\");\n\n    // 1. List all calendars\n    let list_url = \"https://www.googleapis.com/calendar/v3/users/me/calendarList\";\n    let list_resp = client\n        .get(list_url)\n        .bearer_auth(&token)\n        .send()\n        .await\n        .map_err(|e| GwsError::Other(anyhow::anyhow!(\"Failed to list calendars: {e}\")))?;\n\n    if !list_resp.status().is_success() {\n        let err = list_resp.text().await.unwrap_or_default();\n        return Err(GwsError::Api {\n            code: 0,\n            message: err,\n            reason: \"calendarList_failed\".to_string(),\n            enable_url: None,\n        });\n    }\n\n    let list_json: Value = list_resp\n        .json()\n        .await\n        .map_err(|e| GwsError::Other(anyhow::anyhow!(\"Failed to parse calendar list: {e}\")))?;\n\n    let calendars = list_json\n        .get(\"items\")","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/googleworkspace/cli/blob/a3768d0e82ad83cca2da97724e46bea4ff0e6dbd/crates/google-workspace-cli/src/helpers/calendar.rs#L250-L286","documentation":"The +calendar helper's first step is a plain GET of https://www.googleapis.com/calendar/v3/users/me/calendarList. This error wraps only the transport-level failure of that request (reqwest send error): DNS resolution, TCP connect, TLS handshake, proxy refusal, or cancellation — anything before an HTTP status exists. HTTP error statuses are handled separately as GwsError::Api with reason calendarList_failed.","triggerScenarios":"No network / DNS failure for www.googleapis.com; HTTPS_PROXY pointing at a dead proxy; TLS-inspecting corporate proxy rejecting the client cert chain; firewall blocking 443; request timeout.","commonSituations":"Running offline or behind a captive portal; proxy env vars set for a network the machine left; container with broken DNS; VPN split-tunnel excluding Google endpoints.","solutions":["Check basic reachability: curl -sv https://www.googleapis.com/calendar/v3/users/me/calendarList","Verify HTTP_PROXY/HTTPS_PROXY/NO_PROXY values match the current network","Fix DNS/firewall/VPN, then retry — transport failures are transient by nature"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Cheap reachability probe before the helper run\nasync fn googleapi_reachable() -> bool {\n    reqwest::get(\"https://www.googleapis.com\").await.is_ok()\n}","typeGuard":null,"tryCatchPattern":"let mut attempt = 0;\nloop {\n    match list_calendars(&client, &token).await {\n        Ok(cals) => break cals,\n        Err(e) if e.to_string().contains(\"Failed to list calendars\") && attempt < 3 => {\n            attempt += 1;\n            tokio::time::sleep(std::time::Duration::from_secs(2u64.pow(attempt))).await;\n        }\n        Err(e) => return Err(e), // DNS/proxy config problems will not heal — stop and report\n    }\n}","preventionTips":["Validate HTTP(S)_PROXY/NO_PROXY in the environment before long batch runs","Add a connectivity preflight (one cheap GET to googleapis.com) to scripted workflows","Treat repeated transport failures as configuration, not bad luck — check DNS and firewall"],"tags":["calendar","network","http","proxy"],"backgroundTag":"network-request-failed","analyzedSha":"a3768d0e82ad83cca2da97724e46bea4ff0e6dbd","analyzedAt":"2026-08-16T19:51:46.516Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}