googleworkspace/cli · error · GwsError
Failed to parse People API response: {e}
Error message
Failed to parse People API response: {e} What it means
The People API responded 2xx but `resp.json::<Value>()` could not parse the body as JSON. The People API normally returns well-formed JSON, so a malformed body almost always means an intermediary (proxy, captive portal) rewrote the response, or the body was truncated in transit.
Source
Thrown at crates/google-workspace-cli/src/helpers/gmail/mod.rs:667
client
.get("https://people.googleapis.com/v1/people/me")
.query(&[("personFields", "names")])
.bearer_auth(token)
})
.await
.map_err(|e| GwsError::Other(anyhow::anyhow!("People API request failed: {e}")))?;
if !resp.status().is_success() {
let status = resp.status().as_u16();
let body = resp
.text()
.await
.unwrap_or_else(|_| "(error body unreadable)".to_string());
return Err(build_api_error(status, &body, "People API request failed"));
}
let body: Value = resp.json().await.map_err(|e| {
GwsError::Other(anyhow::anyhow!("Failed to parse People API response: {e}"))
})?;
Ok(parse_profile_display_name(&body))
}
/// Extract the display name from a People API `people.get` response.
fn parse_profile_display_name(body: &Value) -> Option<String> {
body.get("names")
.and_then(|v| v.as_array())
.and_then(|names| names.first())
.and_then(|n| n.get("displayName"))
.and_then(|v| v.as_str())
.filter(|s| !s.is_empty())
.map(sanitize_control_chars)
}
/// Fetch binary data for a single attachment from the Gmail API.
///View on GitHub (pinned to a3768d0e82)
Solutions
- Retry the gmail helper command.
- Confirm no proxy rewrites people.googleapis.com responses.
- In tests, stub the endpoint with `{"names": []}` and a JSON content type.
- Log the raw body prefix to identify the interceptor (see example fix pattern).
Defensive patterns
Strategy: validation
Validate before calling
let ct = resp.headers().get(reqwest::header::CONTENT_TYPE).and_then(|v| v.to_str().ok()).unwrap_or("");
if !ct.starts_with("application/json") {
return Err(anyhow::anyhow!("People API returned '{ct}' — likely proxy interception"));
} Type guard
fn is_people_get_response(v: &serde_json::Value) -> bool {
// resourceName is mandatory on people.get responses; names may be absent
v.get("resourceName").and_then(|r| r.as_str()).is_some()
} Try / catch
let text = resp.text().await?;
let body: Value = serde_json::from_str(&text)
.map_err(|e| anyhow::anyhow!("People API invalid JSON ({e}): {}", &text[..text.len().min(120)]))?;
if !is_people_get_response(&body) { return Err(anyhow::anyhow!("unexpected People API envelope")); } Prevention
- Validate content type before json() on People API calls.
- Stub people.googleapis.com with `{"resourceName": "people/me", "names": []}` in tests.
- Retry once before escalating — truncation is transient.
When it happens
Trigger: Intercepting proxy returning an HTML block page with 200; connection cut mid-body so every retry also truncates; stub server in tests returning non-JSON.
Common situations: Same contexts as error 27 — corporate proxies and unstable networks — plus test harnesses that stub people.googleapis.com incorrectly.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse message: {e}
- Failed to parse sendAs response: {e}
- Failed to parse attachment JSON: {e}
- Failed to parse profile: {e}
- Failed to parse calendar list: {e}
AI-assisted analysis of googleworkspace/cli@a3768d0e82 (2026-08-16).
Data as JSON: /api/errors/6a69ed7f83ae9ccb.
Report an issue: GitHub.