{"record":{"id":"40e154f9a3321a27","repo":"tinyhumansai/openhuman","slug":"no-backend-session-store-a-jwt-via-auth-app-sess","errorCode":null,"errorMessage":"No backend session: store a JWT via auth (app-session)","messagePattern":"No backend session: store a JWT via auth \\(app-session\\)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/openhuman/inference/provider/openhuman_backend_model.rs","lineNumber":144,"sourceCode":"        // Managed inference used to fire a doomed request on an expired-but-\n        // stored token and let the 401 come back — but an expired session can\n        // also surface upstream as a misleading \"model unavailable\", which is a\n        // core symptom of #5503 (all tiers \"die\" over a long session). Failing\n        // fast as `session_expired` routes the user to re-auth instead. Offline\n        // / local sessions (`is_local_session_token`) and `exp`-less tokens\n        // carry no recorded expiry, so `classify_session_token` returns `Live`\n        // for them — their behaviour is unchanged and the post-call 401 net\n        // still covers a server-side revocation.\n        match classify_session_token(profile.as_ref(), chrono::Utc::now()) {\n            SessionTokenCheck::Live(token) => Ok(token),\n            SessionTokenCheck::Expired => {\n                maybe_publish_local_session_expiry();\n                anyhow::bail!(\n                    \"SESSION_EXPIRED: backend session token expired locally — re-authentication required\"\n                )\n            }\n            SessionTokenCheck::Absent => {\n                anyhow::bail!(\"No backend session: store a JWT via auth (app-session)\")\n            }\n        }\n    }\n\n    fn base_url(&self) -> String {\n        format!(\n            \"{}/openai/v1\",\n            effective_api_url(&self.api_url).trim_end_matches('/')\n        )\n    }\n\n    /// Resolve the current JWT + base URL and build a fresh crate `OpenAiModel`\n    /// (Bearer). Rebuilt per call because the session JWT rotates.\n    fn build_wire_model(&self) -> TaResult<OpenAiModel> {\n        let token = self\n            .resolve_bearer()\n            .map_err(|e| TinyAgentsError::Model(e.to_string()))?;\n        let base_url = self.base_url();","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/inference/provider/openhuman_backend_model.rs#L126-L162","documentation":"The managed-backend model found no stored app-session JWT at all: `classify_session_token` returned `Absent` because `auth.get_profile(APP_SESSION_PROVIDER, ...)` yielded no profile/token (openhuman_backend_model.rs:~144). Unlike the Expired case there is nothing to check or refresh — the credential was never stored or was lost.","triggerScenarios":"Calling a managed-backend model before any sign-in completed; the auth-profiles store under the state dir has no APP_SESSION_PROVIDER entry (fresh install, workspace reset, `auth_profile_override` pointing at a non-existent profile).","commonSituations":"Onboarding flows that fire an inference call before auth finishes; `auth_profile_override` set to a profile id that doesn't exist; state dir mismatch after migration so the profile lookup reads the wrong store.","solutions":["Complete the sign-in flow so an app-session JWT is stored, then retry.","If using `auth_profile_override`, verify that profile id exists in the auth store.","Confirm the state dir (`~/.openhuman` or the config parent) is the one your sign-in wrote to.","For pre-auth onboarding steps, gate them on auth completion or use a local provider."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let profile = auth.get_profile(APP_SESSION_PROVIDER, override_profile.as_deref())?;\nif profile.is_none() {\n    return prompt_sign_in(); // no stored JWT — the managed call cannot succeed\n}","typeGuard":"fn has_app_session(auth: &AuthService, override_id: Option<&str>) -> bool {\n    auth.get_profile(APP_SESSION_PROVIDER, override_id)\n        .ok()\n        .flatten()\n        .is_some()\n}","tryCatchPattern":null,"preventionTips":["Complete sign-in before any workload selects the managed backend.","If using auth_profile_override, validate the profile id exists.","Gate onboarding inference steps on auth completion or use a local provider."],"tags":["auth","missing-token","app-session","managed-backend"],"backgroundTag":"missing-auth-token","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}