Summary
When a WebUI session ends while a tab is open, the tab never returns to sign-in. Web sessions are held in memory, so any Odin restart or deploy ends them, as does logout elsewhere or token rotation. The tab shows "Unauthorized" with a Retry button, the header shows Offline, and the sidebar shows Reconnecting…, indefinitely. Retry cannot succeed; only a page reload or the logout control recovers. An operator reads this as "Odin is down" when it is only a stale session.
Evidence
- Live, 2026-09-29/30. An operator's open tab polled
GET /api/status every 15 s and received 401 continuously for about 7.5 hours after a deploy restart at 23:19. It had received 200 up to the restart.
- Reproduction (headless Chrome against a live install):
- sign in and load the Dashboard (
/api/status 200);
- invalidate the session server-side with
POST /api/auth/logout from another client;
- after two polls (
/api/status 401, 401) the page shows "Unauthorized" + Retry, "Offline" and "Reconnecting…";
- no login form appears.
- Code:
fetchStatus() in ui/js/app.js catches every error, including AuthError, and only sets botStatus = 'offline';
api.onSessionExpired (which clears the token and sets authState = 'login') is called only from the inactivity monitor in ui/js/api.js, never on a 401.
- The same UI code shipped in v4.10.0, so this is not a v4.11.0 regression.
Expected
- Any 401 from an authenticated WebUI request (status poll, page data, WebSocket auth rejection) ends the local session once.
- The UI stops live polling and returns to the sign-in screen with a short explanation, for example "Your session ended (Odin restarted or the credential changed). Sign in again."
- A deliberate 403 (authenticated but not permitted) must not trigger this.
Out of scope
Whether web sessions should survive restarts (persisting them) is a separate design choice. This issue is only about the stuck state.
Impact
Every install with the WebUI open across a restart, deploy, self-update or credential rotation.
Summary
When a WebUI session ends while a tab is open, the tab never returns to sign-in. Web sessions are held in memory, so any Odin restart or deploy ends them, as does logout elsewhere or token rotation. The tab shows "Unauthorized" with a Retry button, the header shows Offline, and the sidebar shows Reconnecting…, indefinitely. Retry cannot succeed; only a page reload or the logout control recovers. An operator reads this as "Odin is down" when it is only a stale session.
Evidence
GET /api/statusevery 15 s and received 401 continuously for about 7.5 hours after a deploy restart at 23:19. It had received 200 up to the restart./api/status200);POST /api/auth/logoutfrom another client;/api/status401, 401) the page shows "Unauthorized" + Retry, "Offline" and "Reconnecting…";fetchStatus()inui/js/app.jscatches every error, includingAuthError, and only setsbotStatus = 'offline';api.onSessionExpired(which clears the token and setsauthState = 'login') is called only from the inactivity monitor inui/js/api.js, never on a 401.Expected
Out of scope
Whether web sessions should survive restarts (persisting them) is a separate design choice. This issue is only about the stuck state.
Impact
Every install with the WebUI open across a restart, deploy, self-update or credential rotation.