# P0-002: Session Loop Bug (Returned) **Priority:** P0 (Critical) **Source Reference:** From SessionLoopBug.md line 4 **Date Identified:** 2025-11-12 **Previous Fix Attempt:** Commit 7b77641 - "fix: resolve 401 session refresh loop" ## Problem Description The session refresh loop bug has returned. After completing setup and the server restarts, the UI flashes/loops rapidly if you're on the dashboard, agents, or settings pages. Users must manually logout and log back in to stop the loop. ## Reproduction Steps 1. Complete setup wizard in fresh installation 2. Click "Restart Server" button (or restart manually via `docker-compose restart server`) 3. Server goes down, Docker components restart 4. UI automatically redirects from setup to dashboard 5. **BUG:** Screen starts flashing/rapid refresh loop 6. Clicking Logout stops the loop 7. Logging back in works fine ## Root Cause Analysis The issue is in the `SetupCompletionChecker` component which has a dependency array problem in its `useEffect` hook: ```typescript useEffect(() => { const checkSetupStatus = async () => { ... } checkSetupStatus(); const interval = setInterval(checkSetupStatus, 3000); return () => clearInterval(interval); }, [wasInSetupMode, location.pathname, navigate]); // ← Problem here ``` **Issue:** `wasInSetupMode` is in the dependency array. When it changes from `false` to `true` to `false`, it triggers new effect runs, creating multiple overlapping intervals without properly cleaning up the old ones. **During Docker Restart Sequence:** 1. Initial render: creates interval 1 2. Server goes down: can't fetch health, sets `wasInSetupMode` 3. Effect re-runs: interval 1 still running, creates interval 2 4. Server comes back: detects not in setup mode 5. Effect re-runs again: interval 1 & 2 still running, creates interval 3 6. Result: 3+ intervals all polling every 3 seconds = rapid flashing ## Proposed Solution **Option 1: Remove wasInSetupMode from dependencies (Recommended)** ```typescript useEffect(() => { let wasInSetup = false; const checkSetupStatus = async () => { // Use local wasInSetup variable instead of state dependency // ... existing logic using wasInSetup local variable }; checkSetupStatus(); const interval = setInterval(checkSetupStatus, 3000); return () => clearInterval(interval); }, [location.pathname, navigate]); // Only pathname and navigate ``` **Option 2: Add interval guard** ```typescript const [intervalId, setIntervalId] = useState(null); useEffect(() => { // Clear any existing interval first if (intervalId) { clearInterval(intervalId); } const checkSetupStatus = async () => { ... }; checkSetupStatus(); const newInterval = setInterval(checkSetupStatus, 3000); setIntervalId(newInterval); return () => clearInterval(newInterval); }, [wasInSetupMode, location.pathname, navigate]); ``` ## Definition of Done - [ ] No screen flashing/looping after server restart - [ ] Single polling interval active at any time - [ ] Clean redirect to login page after setup completion - [ ] No memory leaks from uncleared intervals - [ ] Setup completion checker continues to work normally ## Test Plan 1. **Fresh Setup Test:** ```bash # Clean start docker-compose down -v --remove-orphans rm config/.env docker-compose build --no-cache cp config/.env.bootstrap.example config/.env docker-compose up -d # Complete setup wizard through UI # Verify dashboard loads normally ``` 2. **Server Restart Test:** ```bash # Restart server manually docker-compose restart server # Watch browser for: # - No multiple "checking setup status" logs # - No 401 errors spamming console # - No rapid API calls to /health endpoint # - Clean behavior (either stays on page or redirects properly) ``` 3. **Console Monitoring Test:** - Open browser developer tools before server restart - Watch console for multiple interval creation logs - Monitor Network tab for duplicate /health requests - Verify only one active polling interval after restart 4. **Memory Leak Test:** - Open browser task manager (Shift+Esc) - Monitor memory usage during multiple server restarts - Verify memory doesn't grow continuously (indicating uncleared intervals) ## Files to Modify - `aggregator-web/src/components/SetupCompletionChecker.tsx` (main component) - Potentially related: `aggregator-web/src/lib/store.ts` (auth store) - Potentially related: `aggregator-web/src/pages/Setup.tsx` (calls logout before configure) ## Impact - **Critical User Experience:** UI becomes unusable after normal server operations - **Production Impact:** Server maintenance/restarts break user experience - **Perceived Reliability:** System appears broken/unstable - **Support Burden:** Users require manual intervention (logout/login) after server restarts ## Technical Notes - This bug only manifests during server restart after setup completion - Previous fix (commit 7b77641) addressed 401 loop but didn't solve interval cleanup - The issue is specific to React effect dependency management - Multiple overlapping intervals cause the rapid flashing behavior ## Verification Commands After implementing fix: ```bash # Monitor browser console during restart # Should see only ONE "checking setup status" log every 3 seconds # Test multiple restarts in succession docker-compose restart server # Wait 10 seconds docker-compose restart server # Wait 10 seconds docker-compose restart server # UI should remain stable throughout ```