tinyhumansai/openhuman · error
Failed to parse Exa response: {e}
Error message
Failed to parse Exa response: {e} What it means
Thrown in post_documents after post() has already delivered parsed JSON: converting the 'results' array of documents/contents endpoints into Vec<ExaResultItem> fails because individual items lack expected fields (id/title/url/text) or carry unexpected types. The transport succeeded; the faulty input is the shape of ExaResultItem entries in the response payload.
Source
Thrown at src/openhuman/search/tools/exa.rs:256
anyhow::bail!(
"Exa rejected the configured API key (HTTP {status}). \
Check your Exa API key under Connections > Search engine."
);
}
anyhow::bail!("Exa returned non-2xx status {status}");
}
resp.json().await.map_err(|e| {
tracing::warn!("[exa] failed to read response JSON: {e}");
anyhow::anyhow!("Failed to read Exa response JSON: {e}")
})
}
async fn post_documents(&self, path: &str, body: Value) -> anyhow::Result<Vec<ExaResultItem>> {
let value = self.post(path, body).await?;
let parsed: ExaSearchResponse = serde_json::from_value(value).map_err(|e| {
tracing::warn!("[exa] failed to parse {path} response: {e}");
anyhow::anyhow!("Failed to parse Exa response: {e}")
})?;
tracing::debug!(path, result_count = parsed.results.len(), "[exa] call ok");
Ok(parsed.results)
}
fn render_plain(&self, results: &[ExaResultItem], heading: &str, limit: usize) -> String {
if results.is_empty() {
return format!("No Exa results for: {heading}");
}
let mut lines = vec![format!("Search results for: {heading} (via Exa)")];
for (i, item) in results.iter().take(limit).enumerate() {
lines.push(format!("{}. {}", i + 1, item.display_title()));
lines.push(format!(" {}", item.url.trim()));
if let Some(date) = non_empty(item.published_date.as_deref()) {
lines.push(format!(" Published: {date}"));
}
if let Some(author) = non_empty(item.author.as_deref()) {View on GitHub (pinned to 7491200858)
Solutions
- Inspect the logged parse error and relax ExaResultItem fields to Option<> where Exa legitimately omits them.
- Add #[serde(default)] / alias attributes to tolerate field renames or additions.
- Log and skip individual unparseable items instead of failing the whole batch.
- Pin a response fixture test to catch Exa schema drift early.
Defensive patterns
Strategy: fallback
When it happens
Trigger: Thrown at src/openhuman/search/tools/exa.rs:256 when the library encounters an invalid state.
Common situations: See trigger scenarios.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/d3f80bced388a04b.
Report an issue: GitHub.