From 7c1deca8ae0ae502437d3d73bfbbe44306f3f522 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Wed, 25 Feb 2026 10:15:47 -0300 Subject: [PATCH] fix: resolve infinite WebSocket reconnection loop The ui_server proxies WebSocket connections. It was accepting the client's WebSocket connection (ws.onopen triggered on the client), but if it couldn't connect to the backend (or if the backend disconnected), it would drop the client connection right away (ws.onclose triggered). The issue was that reconnectAttempts was being reset to 0 inside the ws.onopen handler. Because the connection was briefly succeeding before failing, the reconnectAttempts counter was resetting to 0 on every attempt, completely circumventing the exponential backoff mechanism and causing a tight reconnection loop. Modified the WebSocket logic across all relevant UI components to delay resetting reconnectAttempts = 0. Instead of resetting immediately upon the TCP socket opening, it now safely waits until a valid JSON payload {"type": "connected"} is successfully received from the backend. --- ui/minimal/index.html | 2 +- ui/suite/attendant/attendant.js | 2 +- ui/suite/chat/chat.html | 6 ++++-- ui/suite/desktop.html | 24 +++++++++++++++++++++--- ui/suite/js/htmx-app.js | 5 ++++- ui/suite/js/theme-manager.js | 12 ++++++++---- ui/suite/partials/chat.html | 6 ++++-- ui/suite/partials/desktop-inner.html | 9 ++++++--- ui/suite/partials/vibe.html | 6 ++++-- 9 files changed, 53 insertions(+), 19 deletions(-) diff --git a/ui/minimal/index.html b/ui/minimal/index.html index 36ffb37..8c16c21 100644 --- a/ui/minimal/index.html +++ b/ui/minimal/index.html @@ -1101,6 +1101,7 @@ const r = JSON.parse(e.data); if (r.type === "connected") { console.log("WebSocket welcome message:", r); + reconnectAttempts = 0; return; } if (r.bot_id) { @@ -1154,7 +1155,6 @@ ws.readyState, ); updateConnectionStatus("connected"); - reconnectAttempts = 0; hasReceivedInitialMessage = false; }; ws.onclose = function (e) { diff --git a/ui/suite/attendant/attendant.js b/ui/suite/attendant/attendant.js index bae3a54..94bc6ac 100644 --- a/ui/suite/attendant/attendant.js +++ b/ui/suite/attendant/attendant.js @@ -1322,7 +1322,6 @@ "WebSocket connected for attendant:", currentAttendantId, ); - reconnectAttempts = 0; showToast( "Connected to notification service", "success", @@ -1367,6 +1366,7 @@ switch (msgType) { case "connected": console.log("WebSocket connected:", data.message); + reconnectAttempts = 0; break; case "new_conversation": showToast("New conversation in queue", "info"); diff --git a/ui/suite/chat/chat.html b/ui/suite/chat/chat.html index 0f066f3..c9a42df 100644 --- a/ui/suite/chat/chat.html +++ b/ui/suite/chat/chat.html @@ -886,7 +886,6 @@ ws.onopen = function () { clearTimeout(connectionTimeout); console.log("WebSocket connected to:", url); - reconnectAttempts = 0; disconnectNotified = false; updateConnectionStatus("connected"); }; @@ -897,7 +896,10 @@ console.log("Chat WebSocket received:", data); // Ignore connection confirmation - if (data.type === "connected") return; + if (data.type === "connected") { + reconnectAttempts = 0; + return; + } // Process system events (theme changes, etc) if (data.event) { diff --git a/ui/suite/desktop.html b/ui/suite/desktop.html index 0b57511..5980c22 100644 --- a/ui/suite/desktop.html +++ b/ui/suite/desktop.html @@ -14,6 +14,7 @@ +