From 37842dc1ef5b5f11aec77ba93fb6d52ef013a559 Mon Sep 17 00:00:00 2001 From: Smittix Date: Sun, 8 Feb 2026 13:21:25 +0000 Subject: [PATCH] Fix WebSocket handler exiting immediately on receive timeout simple-websocket 1.1.0's receive(timeout=N) returns None on timeout instead of raising TimeoutError. The handler treated None as "connection closed" and broke out of the loop, causing Werkzeug to write its HTTP 200 response on the still-open WebSocket socket. The browser saw those HTTP bytes as an invalid WebSocket frame. Now checks ws.connected to distinguish timeout (None + connected) from actual close (None + not connected). Co-Authored-By: Claude Opus 4.6 --- routes/waterfall_websocket.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/routes/waterfall_websocket.py b/routes/waterfall_websocket.py index f816cd4..87a5fbc 100644 --- a/routes/waterfall_websocket.py +++ b/routes/waterfall_websocket.py @@ -105,19 +105,22 @@ def init_waterfall_websocket(app: Flask): try: msg = ws.receive(timeout=0.1) - except TimeoutError: - if stop_event.is_set(): - break - continue except Exception as e: - if "closed" in str(e).lower(): + err = str(e).lower() + if "closed" in err: break - if "timed out" not in str(e).lower(): + if "timed out" not in err: logger.error(f"WebSocket receive error: {e}") continue if msg is None: - break + # simple-websocket returns None on timeout AND on + # close; check ws.connected to tell them apart. + if not ws.connected: + break + if stop_event.is_set(): + break + continue try: data = json.loads(msg)