tinyhumansai/openhuman · error

Brave web response shape changed: {e}

Error message

Brave web response shape changed: {e}

What it means

Deserializing the Brave web-search response into the typed `BraveWebResponse` struct failed. The HTTP call succeeded and the body parsed as JSON, but the JSON's field structure does not match what the struct expects — Brave changed or extended their response schema. This is upstream API drift; the parse error is chained so the exact mismatched field is identifiable.

Source

Thrown at src/openhuman/search/tools/brave.rs:229

        args: Value,
        options: ToolCallOptions,
    ) -> anyhow::Result<ToolResult> {
        let query = extract_query(&args)?;
        let count = clamped_count(&args, self.cfg.max_results, 20);
        let mut q: Vec<(&str, String)> = vec![
            ("q", query.clone()),
            ("count", count.to_string()),
            ("result_filter", "web".into()),
        ];
        if let Some(c) = pub_string(&args, "country") {
            q.push(("country", c));
        }
        if let Some(f) = pub_string(&args, "freshness") {
            q.push(("freshness", f));
        }
        let raw = brave_get(&self.cfg, "/web/search", &q).await?;
        let parsed: WebResp = serde_json::from_value(raw)
            .map_err(|e| anyhow::anyhow!("Brave web response shape changed: {e}"))?;
        let results = parsed.web.map(|w| w.results).unwrap_or_default();
        let plain = render_web_plain(&results, &query, count);
        let mut out = ToolResult::success(plain);
        if options.prefer_markdown {
            out.markdown_formatted = Some(render_web_markdown(&results, &query, count));
        }
        Ok(out)
    }
}

fn render_web_plain(results: &[WebResult], query: &str, max: usize) -> String {
    if results.is_empty() {
        return format!("No results found for: {query}");
    }
    let mut lines = vec![format!("Search results for: {query} (via Brave)")];
    for (i, r) in results.iter().take(max).enumerate() {
        let title = if r.title.trim().is_empty() {
            "Untitled"

View on GitHub (pinned to 7491200858)

Solutions

  1. Capture a raw response and diff it against the struct in brave.rs to find the renamed/retyped field
  2. Update the response struct to match the current Brave API shape (check their changelog)
  3. Consider making non-critical new fields `Option<T>`/`#[serde(default)]` so additive upstream changes stop breaking deserialization
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at src/openhuman/search/tools/brave.rs:229 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/850953ce2871c564. Report an issue: GitHub.