{"record":{"id":"cc04222d520bb7e7","repo":"tinyhumansai/openhuman","slug":"brave-news-response-shape-changed-e","errorCode":null,"errorMessage":"Brave news response shape changed: {e}","messagePattern":"Brave news response shape changed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/search/tools/brave.rs","lineNumber":375,"sourceCode":"                \"freshness\": { \"type\": \"string\", \"description\": \"Time filter: 'pd', 'pw', 'pm', 'py'.\" }\n            },\n            \"required\": [\"query\"]\n        })\n    }\n\n    async fn execute(&self, args: Value) -> 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![(\"q\", query.clone()), (\"count\", count.to_string())];\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, \"/news/search\", &q).await?;\n        let parsed: NewsResp = serde_json::from_value(raw)\n            .map_err(|e| anyhow::anyhow!(\"Brave news response shape changed: {e}\"))?;\n        let mut lines = if parsed.results.is_empty() {\n            return Ok(ToolResult::success(format!(\"No news found for: {query}\")));\n        } else {\n            vec![format!(\"News results for: {query} (via Brave)\")]\n        };\n        for (i, r) in parsed.results.iter().take(count).enumerate() {\n            let title = if r.title.trim().is_empty() {\n                \"Untitled\"\n            } else {\n                r.title.trim()\n            };\n            lines.push(format!(\"{}. {}\", i + 1, title));\n            lines.push(format!(\"   {}\", r.url.trim()));\n            if let Some(src) = r.source.as_deref() {\n                let src = src.trim();\n                if !src.is_empty() {\n                    lines.push(format!(\"   Source: {src}\"));\n                }","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/search/tools/brave.rs#L357-L393","documentation":"Deserializing the Brave news-search response into its typed struct failed. Same failure class as the web variant: the request succeeded and the body was valid JSON, but the field structure no longer matches the `BraveNewsResponse` struct — Brave's news endpoint schema drifted from what this parser was built against.","triggerScenarios":"Thrown at src/openhuman/search/tools/brave.rs:375 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Inspect a raw news response and compare it field-by-field with the news struct in brave.rs","Update the struct to match the current schema, preferring `Option<T>` for fields Brave may omit","Pin down whether the change is endpoint-specific — news can drift independently of web"],"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"}