googleworkspace/cli · error · GwsError

Failed to parse People API response

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.

Solutions

  1. Retry the gmail helper command.
  2. Confirm no proxy rewrites people.googleapis.com responses.
  3. In tests, stub the endpoint with `{"names": []}` and a JSON content type.
  4. 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

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

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of googleworkspace/cli@a3768d0e82 (2026-08-16). Data as JSON: /api/errors/6a69ed7f83ae9ccb. Report an issue: GitHub.

Appendix: 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)