tinyhumansai/openhuman · error · BackendApiError::Unauthorized

backend rejected session token on {method} {path}

Error message

backend rejected session token on {method} {path}

What it means

authed_json maps a backend 401 to the typed BackendApiError::Unauthorized: the session token was rejected (expired or revoked). It is an expected session-lapse signal for the auth domain to drive re-login, deliberately kept out of Sentry reporting; every authed endpoint sees it once the session lapses.

Source

Thrown at src/api/rest.rs:669

            // code bug — every authed endpoint will see this once the session
            // lapses. Surface a typed `BackendApiError::Unauthorized` so the
            // auth domain can drive recovery, and skip `report_error` to
            // avoid Sentry noise. Targets `OPENHUMAN-TAURI-4K8` (mascot TTS
            // surfaced it first on `/openai/v1/audio/speech`, but the same
            // shape applies to every `authed_json` path).
            if status_code == 401 {
                tracing::info!(
                    domain = "backend_api",
                    operation = "authed_json",
                    method = method.as_str(),
                    path = url.path(),
                    status = status_code,
                    failure = "non_2xx",
                    "[backend_api] 401 on {} {} — session token rejected, surfacing typed error",
                    method.as_str(),
                    url.path(),
                );
                return Err(anyhow::Error::new(BackendApiError::Unauthorized {
                    method: method.as_str().to_string(),
                    path: url.path().to_string(),
                }));
            }

            // 404 on `/channels/<provider>/messages/<id>` is an expected
            // state (user deleted the message provider-side, or backend
            // GC'd the relay row) — not a code bug. Surface a typed
            // `BackendApiError::MessageNotFound` so callers (`bus.rs`
            // streaming/thinking/delete/final paths) can clear stale
            // ids and skip retry, without funneling the 404 into
            // `report_error`. Targets `OPENHUMAN-TAURI-2Y` (~454 events).
            if status_code == 404 {
                let channel_message = parse_message_path(url.path());
                // A 404 on the *edit* route is normally route absence, not
                // message absence — today the backend implements no `PATCH
                // /channels/:channel/messages/:messageId` at all (#5230). Answer
                // with a distinct typed error so `bus.rs` keeps the message id

View on GitHub (pinned to 7491200858)

Solutions

  1. Refresh the session token or re-authenticate the user
  2. Handle BackendApiError::Unauthorized at the call site by routing to login/recovery instead of retrying with the stale token
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at src/api/rest.rs:669 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/e7edc30693327264. Report an issue: GitHub.