{"record":{"id":"b87f488e4c097f92","repo":"tinyhumansai/openhuman","slug":"brave-image-response-shape-changed-e","errorCode":null,"errorMessage":"Brave image response shape changed: {e}","messagePattern":"Brave image response shape changed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/search/tools/brave.rs","lineNumber":491,"sourceCode":"            \"properties\": {\n                \"query\": { \"type\": \"string\", \"description\": \"Image search query.\" },\n                \"count\": { \"type\": \"integer\", \"description\": \"Max results (1-20).\" },\n                \"country\": { \"type\": \"string\", \"description\": \"2-letter country code.\" }\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        let raw = brave_get(&self.cfg, \"/images/search\", &q).await?;\n        let parsed: ImageResp = serde_json::from_value(raw)\n            .map_err(|e| anyhow::anyhow!(\"Brave image response shape changed: {e}\"))?;\n        if parsed.results.is_empty() {\n            return Ok(ToolResult::success(format!(\"No images found for: {query}\")));\n        }\n        let mut lines = vec![format!(\"Image results for: {query} (via Brave)\")];\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            if let Some(src) = r.properties.as_ref().and_then(|p| p.url.as_deref()) {\n                lines.push(format!(\"   Image: {}\", src.trim()));\n            }\n            lines.push(format!(\"   Page: {}\", r.url.trim()));\n            if let Some(thumb) = r.thumbnail.as_ref().and_then(|t| t.src.as_deref()) {\n                lines.push(format!(\"   Thumb: {}\", thumb.trim()));\n            }","sourceCodeStart":473,"sourceCodeEnd":509,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/search/tools/brave.rs#L473-L509","documentation":"Deserializing the Brave image-search response into its typed struct failed. Same failure class as the web/news variants: valid JSON arrived but its shape does not match the image response struct — Brave's image endpoint schema changed relative to this parser.","triggerScenarios":"Thrown at src/openhuman/search/tools/brave.rs:491 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Fetch a raw image-search response and diff it against the image struct in brave.rs","Update the struct to the current schema, using `Option<T>` where fields may be absent","Check Brave's API changelog — image result fields (thumbnails, source URLs) are the usual drift points"],"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-14T00:17:10.932Z"}