Completed
on 8 Jan 2026, 5:31 pm

Output

🔌 Dashboard Console WebSocket Reconnection Issue

Problem Summary

When mobile browser pauses connections (screen off, app switch), the console WebSocket fails to properly reconnect, while the admin broadcast WebSocket recovers instantly.

Symptoms:

  • Status bar shows "Reconnecting" indefinitely
  • Manual refresh shows "shadow" console - no live updates
  • Assistant text never appears
  • Admin broadcast WebSocket (navbar indicator) reconnects instantly ✓

Root Cause Analysis

Admin Broadcast (works): /api/admin/ws

  • Simple WebSocket that only receives broadcast events
  • Client reconnection in layout.ts:746-790
  • Visibility change handler at line 1231-1237
  • Exponential backoff with 1s reset on visibility

Console WebSocket (broken): /api/console/ws

  • More complex - handles bi-directional messaging (prompts, events, turns)
  • Client reconnection in console-websocket-client.ts:115-145
  • Visibility change handler at lines 290-298
  • 🔴 ISSUE: Recovery state machine not properly notified when WebSocket reconnects

Key Differences Found

Aspect Admin Broadcast Console WS
Visibility Handler Resets backoff to 1s Resets attempts to 0
On Reconnect Simple welcome msg Sends welcome, but no state sync
State Recovery N/A (stateless) Needs to resume/recover turn state
Status Updates N/A Status bar stuck on "Reconnecting"

Specific Issues Identified

1. onopen handler doesn't notify state machine

In console-websocket-client.ts:67-79, when WebSocket reconnects it updates the status dot/label but doesn't dispatch a state machine event to resume the turn.

2. No active turn sync on reconnect

When reconnecting, the server knows if a turn is active (client.currentRequestId) but doesn't send a turn_start message to re-sync the client.

3. attemptRecovery guards prevent re-recovery

In console-recovery.ts:153-156, if state.recoveryComplete is true, recovery is skipped. But after a reconnect, we may need to re-trigger recovery.

4. Status bar not updated post-reconnect

The visibility change handler dispatches page_visible event but the state machine doesn't handle "reconnected and turn in progress" state properly.

Proposed Fixes

  1. Add reconnect state sync to server:
    console-websocket.ts - On WebSocket open, if client has active turn, send turn_start + buffered events
  2. Dispatch state machine event on reconnect:
    console-websocket-client.ts:onopen - Add dispatch({ type: 'reconnect' }) after status update
  3. Handle reconnect in state machine:
    console-sm-transitions.ts - Add reconnect handler that checks for pending state and resumes turn
  4. Reset recovery flags on reconnect:
    console-recovery.ts - Allow re-recovery when WebSocket reconnects during active session

What's Next?

Choose how to proceed:

Quick Actions

Original Request

No layout configured

Details

Type General
Status Completed
Scope vibetools
Tags consolewebsocketmobilereconnectionbug
Created 8 Jan 2026, 5:30 pm
Updated 8 Jan 2026, 5:31 pm
Timing
⏱️ 111.0s
0 tools
TTFE 0% Thinking 100% Tools 0%
Created By claude

Raw Data

{
  "id": "b1b4fee3-8159-4a93-b44b-cf75001423a8",
  "type": "general",
  "status": "completed",
  "title": "Dashboard Console WebSocket Reconnection Issue Analysis",
  "description": "Analysis of mobile reconnection failures vs admin broadcast reliability",
  "context": {
    "output": "<div style=\"background:#1e1e1e;color:#e0e0e0;padding:20px;border-radius:8px;font-family:'Consolas','Monaco',monospace;\">\n<h2 style=\"font-family:sans-serif;color:#fff;margin:0 0 16px 0;\">🔌 Dashboard Console WebSocket Reconnection Issue</h2>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:16px;\">\n<h3 style=\"color:#f59e0b;margin:0 0 12px 0;\">Problem Summary</h3>\n<p style=\"margin:0 0 8px 0;\">When mobile browser pauses connections (screen off, app switch), the console WebSocket fails to properly reconnect, while the admin broadcast WebSocket recovers instantly.</p>\n<p style=\"margin:0;\"><strong>Symptoms:</strong></p>\n<ul style=\"margin:8px 0;padding-left:20px;color:#9ca3af;\">\n<li>Status bar shows \"Reconnecting\" indefinitely</li>\n<li>Manual refresh shows \"shadow\" console - no live updates</li>\n<li>Assistant text never appears</li>\n<li>Admin broadcast WebSocket (navbar indicator) reconnects instantly ✓</li>\n</ul>\n</div>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:16px;\">\n<h3 style=\"color:#22c55e;margin:0 0 12px 0;\">Root Cause Analysis</h3>\n\n<p style=\"margin:0 0 8px 0;\"><strong>Admin Broadcast (works):</strong> <code style=\"color:#98c379;\">/api/admin/ws</code></p>\n<ul style=\"margin:8px 0;padding-left:20px;color:#9ca3af;\">\n<li>Simple WebSocket that only receives broadcast events</li>\n<li>Client reconnection in <code style=\"color:#e5c07b;\">layout.ts:746-790</code></li>\n<li>Visibility change handler at line 1231-1237</li>\n<li>Exponential backoff with 1s reset on visibility</li>\n</ul>\n\n<p style=\"margin:12px 0 8px 0;\"><strong>Console WebSocket (broken):</strong> <code style=\"color:#98c379;\">/api/console/ws</code></p>\n<ul style=\"margin:8px 0;padding-left:20px;color:#9ca3af;\">\n<li>More complex - handles bi-directional messaging (prompts, events, turns)</li>\n<li>Client reconnection in <code style=\"color:#e5c07b;\">console-websocket-client.ts:115-145</code></li>\n<li>Visibility change handler at lines 290-298</li>\n<li><span style=\"color:#ef4444;\">🔴 ISSUE:</span> Recovery state machine not properly notified when WebSocket reconnects</li>\n</ul>\n</div>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:16px;\">\n<h3 style=\"color:#3b82f6;margin:0 0 12px 0;\">Key Differences Found</h3>\n\n<table style=\"width:100%;border-collapse:collapse;font-size:0.9rem;\">\n<tr style=\"background:#1e1e1e;\">\n<th style=\"text-align:left;padding:8px;border-bottom:1px solid #444;\">Aspect</th>\n<th style=\"text-align:left;padding:8px;border-bottom:1px solid #444;\">Admin Broadcast</th>\n<th style=\"text-align:left;padding:8px;border-bottom:1px solid #444;\">Console WS</th>\n</tr>\n<tr>\n<td style=\"padding:8px;border-bottom:1px solid #333;\">Visibility Handler</td>\n<td style=\"padding:8px;border-bottom:1px solid #333;color:#22c55e;\">Resets backoff to 1s</td>\n<td style=\"padding:8px;border-bottom:1px solid #333;color:#22c55e;\">Resets attempts to 0</td>\n</tr>\n<tr>\n<td style=\"padding:8px;border-bottom:1px solid #333;\">On Reconnect</td>\n<td style=\"padding:8px;border-bottom:1px solid #333;color:#22c55e;\">Simple welcome msg</td>\n<td style=\"padding:8px;border-bottom:1px solid #333;color:#ef4444;\">Sends welcome, but no state sync</td>\n</tr>\n<tr>\n<td style=\"padding:8px;border-bottom:1px solid #333;\">State Recovery</td>\n<td style=\"padding:8px;border-bottom:1px solid #333;color:#9ca3af;\">N/A (stateless)</td>\n<td style=\"padding:8px;border-bottom:1px solid #333;color:#ef4444;\">Needs to resume/recover turn state</td>\n</tr>\n<tr>\n<td style=\"padding:8px;border-bottom:1px solid #333;\">Status Updates</td>\n<td style=\"padding:8px;border-bottom:1px solid #333;color:#9ca3af;\">N/A</td>\n<td style=\"padding:8px;border-bottom:1px solid #333;color:#ef4444;\">Status bar stuck on \"Reconnecting\"</td>\n</tr>\n</table>\n</div>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:16px;\">\n<h3 style=\"color:#8b5cf6;margin:0 0 12px 0;\">Specific Issues Identified</h3>\n\n<p style=\"margin:0 0 8px 0;\"><strong>1. onopen handler doesn't notify state machine</strong></p>\n<p style=\"color:#9ca3af;margin:0 0 12px 0;\">In <code>console-websocket-client.ts:67-79</code>, when WebSocket reconnects it updates the status dot/label but doesn't dispatch a state machine event to resume the turn.</p>\n\n<p style=\"margin:0 0 8px 0;\"><strong>2. No active turn sync on reconnect</strong></p>\n<p style=\"color:#9ca3af;margin:0 0 12px 0;\">When reconnecting, the server knows if a turn is active (<code>client.currentRequestId</code>) but doesn't send a <code>turn_start</code> message to re-sync the client.</p>\n\n<p style=\"margin:0 0 8px 0;\"><strong>3. attemptRecovery guards prevent re-recovery</strong></p>\n<p style=\"color:#9ca3af;margin:0 0 12px 0;\">In <code>console-recovery.ts:153-156</code>, if <code>state.recoveryComplete</code> is true, recovery is skipped. But after a reconnect, we may need to re-trigger recovery.</p>\n\n<p style=\"margin:0 0 8px 0;\"><strong>4. Status bar not updated post-reconnect</strong></p>\n<p style=\"color:#9ca3af;margin:0 0 12px 0;\">The visibility change handler dispatches <code>page_visible</code> event but the state machine doesn't handle \"reconnected and turn in progress\" state properly.</p>\n</div>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-bottom:16px;\">\n<h3 style=\"color:#f59e0b;margin:0 0 12px 0;\">Proposed Fixes</h3>\n\n<ol style=\"margin:0;padding-left:20px;line-height:2;\">\n<li><strong>Add reconnect state sync to server:</strong><br>\n<code style=\"color:#98c379;\">console-websocket.ts</code> - On WebSocket open, if client has active turn, send <code>turn_start</code> + buffered events</li>\n\n<li><strong>Dispatch state machine event on reconnect:</strong><br>\n<code style=\"color:#98c379;\">console-websocket-client.ts:onopen</code> - Add <code>dispatch({ type: 'reconnect' })</code> after status update</li>\n\n<li><strong>Handle reconnect in state machine:</strong><br>\n<code style=\"color:#98c379;\">console-sm-transitions.ts</code> - Add reconnect handler that checks for pending state and resumes turn</li>\n\n<li><strong>Reset recovery flags on reconnect:</strong><br>\n<code style=\"color:#98c379;\">console-recovery.ts</code> - Allow re-recovery when WebSocket reconnects during active session</li>\n</ol>\n</div>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;\">\n<h4 style=\"margin:0 0 8px 0;color:#fff;\">What's Next?</h4>\n<p style=\"color:#9ca3af;margin:0;\">Choose how to proceed:</p>\n</div>\n</div>",
    "requestedAt": "2026-01-08T07:30:00Z",
    "requestId": "58e88da5-cea2-4977-9acb-8b90fbd936d4",
    "choices": [
      {
        "label": "Implement Fix",
        "value": "Implement the WebSocket reconnection fixes identified in the analysis. Start with adding state sync on reconnect to console-websocket.ts",
        "primary": true
      },
      {
        "label": "Debug Session",
        "value": "Set up a debug session to capture logs during mobile reconnection failure - add more verbose logging first"
      },
      {
        "label": "Quick Workaround",
        "value": "Implement a quick workaround - force page reload when WebSocket reconnects after extended disconnect"
      }
    ],
    "turnTiming": {
      "totalMs": 110983,
      "ttfeMs": 221,
      "thinkingMs": 110760,
      "toolExecutionMs": 0,
      "toolCallCount": 0,
      "thinkingPct": 100,
      "toolsPct": 0,
      "ttfePct": 0
    }
  },
  "createdBy": "claude",
  "createdAt": "2026-01-08T07:30:52.973Z",
  "updatedAt": "2026-01-08T07:31:01.259Z",
  "requestId": "58e88da5-cea2-4977-9acb-8b90fbd936d4",
  "scope": "vibetools",
  "tags": [
    "console",
    "websocket",
    "mobile",
    "reconnection",
    "bug"
  ],
  "targetUser": "claude"
}
DashboardReportsKontasksFlowsDecisionsSessionsTelemetryLogs + Go