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
- Capture a raw response and diff it against the struct in brave.rs to find the renamed/retyped field
- Update the response struct to match the current Brave API shape (check their changelog)
- 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.