googleworkspace/cli · warning · GwsError
5
5
Error message
Failed to fetch account timezone: {e} What it means
`fetch_account_timezone()`'s GET to `https://www.googleapis.com/calendar/v3/users/me/settings/timezone` failed at the transport layer (DNS, connection, TLS, proxy) before any status code existed. Note this is a *soft* failure in practice: `resolve_account_timezone()` catches it, logs a warning, and falls back to the machine-local timezone (step 4 of its priority chain), so the command usually still completes — possibly with wrong-day boundaries for users whose machine tz differs from their calendar tz.
Source
Thrown at crates/google-workspace-cli/src/timezone.rs:85
if let Err(e) = std::fs::create_dir_all(parent) {
tracing::warn!(path = %parent.display(), error = %e, "failed to create timezone cache directory");
return;
}
}
if let Err(e) = std::fs::write(&path, tz_name) {
tracing::warn!(path = %path.display(), error = %e, "failed to write timezone cache");
}
}
/// Fetch the account timezone from the Google Calendar Settings API.
async fn fetch_account_timezone(client: &reqwest::Client, token: &str) -> Result<Tz, GwsError> {
let url = "https://www.googleapis.com/calendar/v3/users/me/settings/timezone";
let resp = client
.get(url)
.bearer_auth(token)
.send()
.await
.map_err(|e| GwsError::Other(anyhow::anyhow!("Failed to fetch account timezone: {e}")))?;
if !resp.status().is_success() {
let status = resp.status();
let body = resp.text().await.unwrap_or_default();
return Err(GwsError::Api {
code: status.as_u16(),
message: body,
reason: "timezone_fetch_failed".to_string(),
enable_url: None,
});
}
let json: serde_json::Value = resp
.json()
.await
.map_err(|e| GwsError::Other(anyhow::anyhow!("Failed to parse timezone response: {e}")))?;
let tz_name = jsonView on GitHub (pinned to a3768d0e82)
Solutions
- Pass `--timezone America/Denver` (any IANA name) — priority 1, skips the network fetch entirely.
- Restore egress to www.googleapis.com and retry; a successful fetch repopulates the 24h cache.
- Check proxy env vars if a middlebox is breaking the request.
- If you rely on calendar-day accuracy in automation, always set --timezone explicitly rather than depending on the silent local-machine fallback.
Example fix
# before — silent fallback to machine tz when offline GOOGLE_WORKSPACE_CLI_LOG=warn gws calendar +standup-report # stderr: failed to fetch account timezone, falling back to local # after — pin the zone, no fetch needed gws calendar +standup-report --timezone Europe/Berlin
Defensive patterns
Strategy: fallback
Validate before calling
// Skip the network fetch when the zone is known
if let Some(tz) = std::env::var("GWS_TZ").ok() {
args.push(format!("--timezone={tz}")); // priority-1 override, no HTTP call
} Try / catch
// resolve_account_timezone already implements the recommended pattern:
// fetch failure -> warn -> machine-local fallback. Wrap callers to surface it:
match timezone::resolve_account_timezone(&client, &token, override_tz).await {
Ok(tz) => tz,
Err(e) => chrono_tz::UTC, // belt-and-braces: never fail a report for timezone reasons
} Prevention
- Pass --timezone explicitly in scheduled reports so results never depend on network availability.
- Keep the machine timezone correct — it is the silent fallback.
- Watch for the 'falling back to local' warning in stderr when accuracy matters.
When it happens
Trigger: First run of a date-aware helper (`+standup-report`, `+focus`, etc.) with no timezone cache and no `--timezone` flag while offline or behind a broken proxy; DNS failure for www.googleapis.com; ADC/service environments without external egress.
Common situations: Egress-restricted CI; cached timezone older than 24h expiring exactly when the network is down; machines set to UTC while the Google account lives in another zone (silent boundary shift after fallback).
Related errors
- Failed to list calendars: {e}
- Pub/Sub pull failed: {e}
- Failed to fetch message: {e}
- Failed to fetch sendAs settings: {e}
- People API request failed: {e}
AI-assisted analysis of googleworkspace/cli@a3768d0e82 (2026-08-16).
Data as JSON: /api/errors/5b1672ca2f316d1e.
Report an issue: GitHub.