tinyhumansai/openhuman · error
API request failed
Error message
API request failed: {message} What it means
authed_json unwraps the TinyHumans backend's { success, data, user } envelope; when the parsed JSON body has success=false it bails with 'API request failed: {message}', taking the body's message or error field ('request unsuccessful' when neither exists). It means the backend received and answered the request with a business-level failure - distinct from transport errors and from the separately-handled 401/404 statuses.
Solutions
- Inspect the embedded {message} - it is the backend's own failure text and usually names the exact problem.
- Verify the request payload against the current vendored SDK route definition (the SDK is the source of truth for routes and params).
- Check for version skew between the app, the vendored SDK submodule, and the backend.
- If the message smells like auth but the call got this far, remember real 401 session expiry is classified separately - this path is a body-level rejection.
Defensive patterns
Strategy: try-catch
Try / catch
In Rust callers, match on the anyhow error: if the message starts with 'API request failed:', surface the remainder (the backend's message) to the user as a validation or entitlement problem; otherwise propagate. When using SDK-typed routes, prefer classify_sdk_error so Sentry and session-expiry behavior stay consistent.
Prevention
- Validate request payloads client-side against the vendored SDK route definitions before sending.
- Keep app, SDK submodule, and backend versions aligned to avoid envelope-contract drift.
- Log method plus path alongside the error for correlation.
When it happens
Trigger: Any SDK-backed authed_json call whose backend handler responds 2xx-wrapped (or 200-with) success=false: invalid or newly-required parameters, entitlement or plan restrictions, semantically rejected payloads, or account-level feature flags.
Common situations: A backend rollout tightened validation and the client still sends the old payload shape; a newly required field was missed; the account lacks an entitlement the route checks.
Related errors
- Backend error for
- failed ( )
- Failed to send magic link
- HTTP error! status
- agent ` ` is a `worker` tier and must not list ` ` in its…
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/c727a2712fa664df.
Report an issue: GitHub.
Appendix: source
Thrown at src/api/rest.rs:311
/// than `{success,data}`; SDK transport must not expose that envelope detail to
/// existing callers.
fn parse_api_response_value(value: Value) -> Result<Value> {
let Some(object) = value.as_object() else {
return Ok(value);
};
if let Some(user) = object.get("user").filter(|user| !user.is_null()) {
return Ok(user.clone());
}
let Some(success) = object.get("success").and_then(Value::as_bool) else {
return Ok(value);
};
if !success {
let message = object
.get("message")
.or_else(|| object.get("error"))
.and_then(Value::as_str)
.unwrap_or("request unsuccessful");
anyhow::bail!("API request failed: {message}");
}
if let Some(data) = object.get("data").filter(|data| !data.is_null()) {
return Ok(data.clone());
}
if let Some(user) = object.get("user").filter(|user| !user.is_null()) {
return Ok(user.clone());
}
let mut unwrapped = object.clone();
unwrapped.remove("success");
Ok(Value::Object(unwrapped))
}
fn user_id_from_object(obj: &serde_json::Map<String, Value>) -> Option<String> {
for key in ["id", "_id", "userId"] {
if let Some(s) = obj.get(key).and_then(|x| x.as_str()) {
let t = s.trim();
if !t.is_empty() {
return Some(t.to_string());View on GitHub (pinned to 7491200858)