tinyhumansai/openhuman · error
{} {} failed ({status}): {text}
Error message
{} {} failed ({status}): {text} What it means
The generic non-2xx failure bail inside authed_json: "{method} {path} failed ({status}): {body}" for any response that is not 2xx and not specially classified (401 session-expiry, channel-message 404, announcements-latest 404 have their own typed paths). It carries the raw status and response text, so the root cause must be read from those. Transient statuses are logged, not Sentry-reported; this bail is the catch-all remainder.
Source
Thrown at src/api/rest.rs:848
"{} {} failed ({status}); response_body_len={}; body_shape={}",
method.as_str(),
url.path(),
text.len(),
body_shape,
)
.as_str(),
"backend_api",
"authed_json",
&[
("method", method.as_str()),
("path", url.path()),
("host", host),
("status", status_str.as_str()),
("failure", "non_2xx"),
],
);
}
anyhow::bail!(
"{} {} failed ({status}): {text}",
method.as_str(),
url.path()
);
}
}
/// Lists all active integrations for the current user.
pub async fn list_integrations(&self, bearer_jwt: &str) -> Result<Vec<IntegrationSummary>> {
let value = self
.authed_json(bearer_jwt, Method::GET, "auth/integrations", None)
.await?;
let integrations = value
.get("integrations")
.cloned()
.unwrap_or_else(|| value.clone());
serde_json::from_value(integrations).context("parse integrations response")
}View on GitHub (pinned to a221052e0d)
Solutions
- Read the status and text embedded in the message — they name the actual backend complaint
- 404: confirm the route exists on the deployed backend version and the path/params are correct
- 400/422: diff your request body against the backend schema; usually field-name or type drift
- 429/5xx: retry with backoff (transient by design); check backend health before retrying hard
Example fix
// before
let v = client.authed_json(&jwt, Method::POST, path, Some(body)).await?;
// after
let v = match client.authed_json(&jwt, Method::POST, path, Some(body)).await {
Ok(v) => v,
Err(err) => {
let msg = err.to_string();
if msg.contains("failed (429)") || msg.contains("failed (5") {
tokio::time::sleep(Duration::from_secs(2)).await;
client.authed_json(&jwt, Method::POST, path, Some(body)).await?
} else {
return Err(err.context(format!("call {path} rejected")));
}
}
}; Defensive patterns
Strategy: retry
Type guard
fn status_from_err(err: &anyhow::Error) -> Option<u16> {
let msg = err.to_string();
let mid = msg.split("failed (").nth(1)?;
mid.split(')').next()?.parse().ok()
} Try / catch
const MAX_ATTEMPTS: u32 = 3;
for attempt in 1..=MAX_ATTEMPTS {
match client.authed_json(&jwt, method, path, body.clone()).await {
Ok(v) => break Ok(v),
Err(err) => match status_from_err(&err) {
Some(429) | Some(500..=599) if attempt < MAX_ATTEMPTS => {
tokio::time::sleep(Duration::from_millis(250 * 2u64.pow(attempt - 1))).await;
}
_ => break Err(err.context(format!("{path} rejected"))),
},
}
}?; Prevention
- Read the embedded status+text before choosing a remedy; 4xx (except 429) will not fix themselves
- Wrap bursty polling with jittered backoff to avoid 429s
- Log method/path/status together (as authed_json already does) so failures triage fast
When it happens
Trigger: Any authed_json / SDK call hitting 400 (bad body), 403 (forbidden), 404 on an unclassified route, 409, 429, or 5xx — e.g. sending a malformed integration payload, calling a route the backend version does not have, or a backend outage.
Common situations: Expired-but-not-401 credentials on a scoped route, request body schema drift after a backend deploy, rate limiting on bursty polling, backend 502/503 during deploys, or pointing the client at the wrong environment (staging route missing in prod).
Related errors
- API base URL must be an absolute http(s) URL with host
- consume login token response missing jwt
- [transport:manager] all transports failed to connect
- spawned core exited with ${child.exitCode} ${stderrFn()}
- timed out waiting for core at ${coreUrl} ${stderrFn()}
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/5a6c43b352de8bc5.
Report an issue: GitHub.