{"record":{"id":"850953ce2871c564","repo":"tinyhumansai/openhuman","slug":"brave-web-response-shape-changed-e","errorCode":null,"errorMessage":"Brave web response shape changed: {e}","messagePattern":"Brave web response shape changed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/search/tools/brave.rs","lineNumber":229,"sourceCode":"        args: Value,\n        options: ToolCallOptions,\n    ) -> anyhow::Result<ToolResult> {\n        let query = extract_query(&args)?;\n        let count = clamped_count(&args, self.cfg.max_results, 20);\n        let mut q: Vec<(&str, String)> = vec![\n            (\"q\", query.clone()),\n            (\"count\", count.to_string()),\n            (\"result_filter\", \"web\".into()),\n        ];\n        if let Some(c) = pub_string(&args, \"country\") {\n            q.push((\"country\", c));\n        }\n        if let Some(f) = pub_string(&args, \"freshness\") {\n            q.push((\"freshness\", f));\n        }\n        let raw = brave_get(&self.cfg, \"/web/search\", &q).await?;\n        let parsed: WebResp = serde_json::from_value(raw)\n            .map_err(|e| anyhow::anyhow!(\"Brave web response shape changed: {e}\"))?;\n        let results = parsed.web.map(|w| w.results).unwrap_or_default();\n        let plain = render_web_plain(&results, &query, count);\n        let mut out = ToolResult::success(plain);\n        if options.prefer_markdown {\n            out.markdown_formatted = Some(render_web_markdown(&results, &query, count));\n        }\n        Ok(out)\n    }\n}\n\nfn render_web_plain(results: &[WebResult], query: &str, max: usize) -> String {\n    if results.is_empty() {\n        return format!(\"No results found for: {query}\");\n    }\n    let mut lines = vec![format!(\"Search results for: {query} (via Brave)\")];\n    for (i, r) in results.iter().take(max).enumerate() {\n        let title = if r.title.trim().is_empty() {\n            \"Untitled\"","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/search/tools/brave.rs#L211-L247","documentation":"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.","triggerScenarios":"Thrown at src/openhuman/search/tools/brave.rs:229 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","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"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}