tinyhumansai/openhuman · error · anyhow::Error
SESSION_EXPIRED: backend session not active — sign in to use
Error message
SESSION_EXPIRED: backend session not active — sign in to use custom providers
What it means
The custom-provider session gate in the chat factory refuses to proceed because `cron::scheduler_gate::is_signed_out()` reports the backend session as dead (factory.rs:~1899 fast path). Custom (BYOK) cloud providers require an active app session; AgentBox mode explicitly bypasses this gate. The `SESSION_EXPIRED:` prefix is the standard marker the frontend routes to re-auth.
Source
Thrown at src/openhuman/inference/provider/factory.rs:1892
/// construction-time chokepoint can never diverge on what "session active"
/// means.
pub(crate) fn verify_session_active(config: &Config) -> anyhow::Result<()> {
// AgentBox marketplace containers run headless with no desktop
// `app-session` JWT — the deployment is operator-controlled and ships its
// own GMI MaaS credentials via `GMI_*` env vars. The session gate exists to
// stop an *unregistered desktop user* from routing every workload at a
// custom provider; that threat model doesn't apply here, so bypass it.
// Without this, every `/run` job would fail `SESSION_EXPIRED` before
// reaching GMI (the startup path stores only `provider:gmi-maas`).
if crate::openhuman::agent::agentbox::agentbox_mode_enabled() {
log::debug!(
"[chat-factory] AgentBox mode — bypassing app-session gate for custom provider"
);
return Ok(());
}
// Fast path: the scheduler gate already knows the session is dead.
if crate::openhuman::cron::scheduler_gate::is_signed_out() {
anyhow::bail!(
"SESSION_EXPIRED: backend session not active — sign in to use custom providers"
);
}
// Verify the app-session JWT actually exists in auth-profiles.
let state_dir = config
.config_path
.parent()
.map(std::path::PathBuf::from)
.unwrap_or_else(|| {
directories::UserDirs::new()
.map(|d| d.home_dir().join(".openhuman"))
.unwrap_or_else(|| std::path::PathBuf::from(".openhuman"))
});
let auth = AuthService::new(&state_dir, config.secrets.encrypt);
let has_session = auth
.get_provider_bearer_token(
crate::openhuman::security::credentials::APP_SESSION_PROVIDER,
None,View on GitHub (pinned to 7491200858)
Solutions
- Sign in again via the app's auth flow — the gate re-checks live state on the next request.
- If this recurs immediately after sign-in, restart the core so the scheduler gate clears its cached signed-out state.
- Agents running under AgentBox are exempt — verify you are not unintentionally outside that mode.
- If you intended fully local operation, switch the provider to a local runtime which never crosses this gate.
Defensive patterns
Strategy: try-catch
Validate before calling
if crate::openhuman::cron::scheduler_gate::is_signed_out() {
return Err(anyhow::anyhow!("SESSION_EXPIRED")); // route UI to re-auth before the call
} Try / catch
match build_provider(&config).await {
Err(e) if e.to_string().starts_with("SESSION_EXPIRED") => route_to_re_auth(),
other => other,
} Prevention
- Handle sign-out events by pausing cloud-role workloads until re-auth completes.
- Remember AgentBox mode intentionally bypasses this gate — verify your mode matches intent.
- Treat any `SESSION_EXPIRED:`-prefixed error as an auth-routing signal, not a provider bug.
When it happens
Trigger: Resolving a custom/BYOK cloud provider for a chat request after sign-out was recorded — token revocation, explicit logout, or the scheduler gate observing a 401. Not triggered in AgentBox mode (`agentbox_mode_enabled()` returns early).
Common situations: Long-running desktop session whose JWT was revoked server-side; user signed out in one window while a chat/cron workload fired in another; session invalidated by a password change or device management.
Related errors
- SESSION_EXPIRED: no backend session — sign in to use OpenHum
- SESSION_EXPIRED: backend session not active — sign in to res
- Failed to send magic link (${response.status})
- Request timed out. Please try again.
- Login token invalid or expired
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/0c14d6a5a7a9ce9c.
Report an issue: GitHub.