From fee1f8c92c398c0cf9e7ef18d1c19df7956fd685 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 1 Feb 2026 14:06:33 +0000 Subject: [PATCH] Fix WebSocket 'Invalid frame header' error by disabling WebSocket transport This change resolves the WebSocket connection error that occurs when Cloudflare or other reverse proxies block WebSocket upgrade attempts. Changes: - Frontend: Configure Socket.IO client to use polling-only transport - Backend: Add documentation comment about transport configuration - Remove WebSocket URL conversion (no longer needed for polling) The error occurred because: 1. Socket.IO started with HTTP polling (successful) 2. Attempted to upgrade to WebSocket (blocked by Cloudflare) 3. Browser received invalid/blocked frames causing "Invalid frame header" 4. Eventually fell back to polling (working) With this fix: - Socket.IO uses HTTP long-polling exclusively - No WebSocket upgrade attempts - No "Invalid frame header" errors - Connection remains stable through Cloudflare Polling transport provides equivalent functionality and reliability. https://claude.ai/code/session_mmQs0 --- backend/app.py | 2 ++ frontend/lib/hooks/useInteractiveTerminal.ts | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/app.py b/backend/app.py index ea1c0ab..bee4060 100644 --- a/backend/app.py +++ b/backend/app.py @@ -22,6 +22,8 @@ app = Flask(__name__) CORS(app, resources={r"/*": {"origins": "*"}}) # Initialize SocketIO +# Note: Frontend uses polling-only transport due to Cloudflare/reverse proxy +# blocking WebSocket connections. Server supports both transports. socketio = SocketIO( app, cors_allowed_origins="*", diff --git a/frontend/lib/hooks/useInteractiveTerminal.ts b/frontend/lib/hooks/useInteractiveTerminal.ts index 1b599b9..b8cc5ac 100644 --- a/frontend/lib/hooks/useInteractiveTerminal.ts +++ b/frontend/lib/hooks/useInteractiveTerminal.ts @@ -114,9 +114,10 @@ export function useInteractiveTerminal({ (window as any)._debugTerminal = term; } - const wsUrl = API_BASE_URL.replace(/^http/, 'ws'); - socket = io(`${wsUrl}/terminal`, { - transports: ['polling', 'websocket'], + // Use polling only - WebSocket is blocked by Cloudflare/reverse proxy + // This prevents "Invalid frame header" errors during upgrade attempts + socket = io(`${API_BASE_URL}/terminal`, { + transports: ['polling'], reconnectionDelayMax: 10000, timeout: 60000, forceNew: true,