{"record":{"id":"dc80b2a5dd5b885f","repo":"zeroclaw-labs/zeroclaw","slug":"nevis-session-validation-returned-http","errorCode":null,"errorMessage":"Nevis session validation returned HTTP {}","messagePattern":"Nevis session validation returned HTTP (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/security/nevis.rs","lineNumber":268,"sourceCode":"            bail!(\"empty session token\");\n        }\n\n        let session_url = format!(\n            \"{}/auth/realms/{}/protocol/openid-connect/userinfo\",\n            self.instance_url.trim_end_matches('/'),\n            self.realm,\n        );\n\n        let resp = self\n            .http_client\n            .get(&session_url)\n            .bearer_auth(session_token)\n            .send()\n            .await\n            .context(\"Failed to reach Nevis userinfo endpoint\")?;\n\n        if !resp.status().is_success() {\n            bail!(\n                \"Nevis session validation returned HTTP {}\",\n                resp.status().as_u16()\n            );\n        }\n\n        let body: UserInfoResponse = resp\n            .json()\n            .await\n            .context(\"Failed to parse Nevis userinfo response\")?;\n\n        if body.sub.trim().is_empty() {\n            bail!(\"Userinfo response has missing or empty `sub` claim\");\n        }\n\n        let now = std::time::SystemTime::now()\n            .duration_since(std::time::UNIX_EPOCH)\n            .unwrap_or_default()\n            .as_secs();","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/security/nevis.rs#L250-L286","documentation":"validate_session GETs {instance_url}/auth/realms/{realm}/protocol/openid-connect/userinfo with the session token as bearer (nevis.rs:259-272). A non-2xx answer produces this error. 401 typically means the session token is invalid or expired; 404 means wrong instance_url or realm.","triggerScenarios":"validate_session with a stale or revoked session cookie; wrong realm in provider config; Nevis or its reverse proxy returning 5xx during an outage.","commonSituations":"User's server-side session expired while the cookie persisted; realm renamed on the IdP; a proxy rewrite strips the Authorization header in transit.","solutions":["For HTTP 401, clear the session cookie and send the user to login — do not retry the same token","For 404, verify instance_url and realm (provider.realm() shows the configured value)","For 5xx, retry with backoff and surface an 'authentication service unavailable' state instead of logging users out"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"Parse the trailing HTTP code: 401 -> clear the session cookie and redirect to login; 404 -> alert on realm/URL misconfig; 5xx -> return 503 with Retry-After and retry with backoff.","preventionTips":["Track session expiry client-side so known-dead cookies are not sent","Split 401 (user problem) from 5xx (IdP problem) in metrics and alerts","Keep realm and instance_url in one config source shared by all environments"],"tags":["auth","nevis","oauth","userinfo","http-status","rust"],"backgroundTag":"oauth-userinfo-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}