tinyhumansai/openhuman · error
Smithery returned HTTP {status}: {}
Error message
Smithery returned HTTP {status}: {} What it means
Raised by the Smithery MCP-catalog client when a paginated search against the Smithery registry returns any non-2xx HTTP status. The request itself completed (auth headers were already attached by apply_auth), so the status is Smithery's — or an intermediary proxy's — answer, not a transport failure. The message embeds the status code plus the first 200 bytes of the response body so the upstream API's own error text is visible; a warn! with the cache key is also emitted.
Source
Thrown at src/openhuman/mcp/registry/registries/smithery.rs:77
let mut req = client.get(format!("{SMITHERY_BASE}/servers"));
if !q.is_empty() {
req = req.query(&[("q", q)]);
}
req = req
.query(&[
("page", &page.to_string()),
("pageSize", &page_size.to_string()),
])
.header("Accept", "application/json");
req = apply_auth(config, req);
let resp = req.send().await.context("Smithery search request failed")?;
let status = resp.status();
let body = resp.text().await.context("Smithery search read failed")?;
if !status.is_success() {
tracing::warn!("[smithery] search HTTP {status} for key={cache_key}");
anyhow::bail!(
"Smithery returned HTTP {status}: {}",
&body[..body.len().min(200)]
);
}
let parsed: SmitheryListResponse = serde_json::from_str(&body)
.with_context(|| format!("Failed to parse Smithery list response: {body}"))?;
let total_pages = parsed.pagination.total_pages;
let servers = tag_source(parsed.servers);
let _ = store::set_cached(config, &cache_key, &body);
tracing::debug!(
"[smithery] search ok servers={} total_pages={}",
servers.len(),
total_pages
);
View on GitHub (pinned to 7491200858)
Solutions
- Reproduce outside the app: curl -i 'https://registry.smithery.ai/servers?q=<query>' and read the status and body.
- For 401/403, fix or remove the Smithery credentials that apply_auth attaches (the config-managed API key), then retry.
- For 429/5xx, wait a few seconds and retry — these are transient, and previously cached pages (store::set_cached) still serve the UI.
- For proxy interference (407/502 from a middlebox), allowlist registry.smithery.ai or bypass the proxy.
Example fix
// before
let page = registry.search(config, &query, page, page_size).await?;
// after — retry transient statuses once, fail fast on auth errors
let page = match registry.search(config, &query, page, page_size).await {
Ok(p) => p,
Err(e) if e.to_string().contains("HTTP 429") || e.to_string().contains("HTTP 5") => {
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
registry.search(config, &query, page, page_size).await?
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: retry
Validate before calling
// Preflight: can we reach the Smithery registry at all?
async fn smithery_reachable(client: &reqwest::Client) -> bool {
const BASE: &str = "https://registry.smithery.ai"; // same host the registry client uses
match client.head(BASE).send().await {
Ok(resp) => !resp.status().is_server_error(),
Err(_) => false,
}
} Try / catch
Inspect the embedded status in err.to_string(): treat `HTTP 401`/`HTTP 403` as a credentials bug (do not retry), `HTTP 429`/`HTTP 5xx` as transient (retry with seconds-scale backoff), anything else as network/proxy. Log the 200-byte body prefix — it carries Smithery's own message.
Prevention
- Keep a valid Smithery API key configured where apply_auth expects it.
- Rate-limit catalog refresh loops — sleep between pages instead of hammering search.
- Rely on the built-in response cache for read paths so outages degrade gracefully.
- Monitor registry status and fail soft in UI search results.
When it happens
Trigger: Calling the registry search flow (SmitheryRegistry::search with query/page/pageSize, the query params visible in the source) when Smithery answers 401/403 (invalid or missing API key attached by apply_auth), 429 (catalog rate limit during bulk or scripted installs), 5xx (registry outage), or when a corporate TLS-inspection proxy answers 407/502 for registry.smithery.ai.
Common situations: Expired or wrong Smithery API key in config; install scripts looping over catalog pages until rate-limited; VPN/proxy environments; Smithery API host or schema change after a registry update; a fully offline machine requesting a cache key that store::set_cached never populated.
Related errors
- Smithery GET {qualified_name} returned HTTP {status}: {}
- MCP official registry GET {qualified_name} returned HTTP {st
- MCP official registry returned HTTP {status}: {}
- manifest fetch failed (${res.status})
- MCP events GET {} — {}
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/754a1ece39c3d6c4.
Report an issue: GitHub.