From be3bfafeaae102ac036df41f5436104a32f7f747 Mon Sep 17 00:00:00 2001 From: Quick104 <31828688+Quick104@users.noreply.github.com> Date: Tue, 14 Jul 2026 13:44:36 -0400 Subject: [PATCH] fix(api): log events websocket upgrade failures with handshake shape The events handler silently swallowed gorilla upgrade errors, which hid a client bug that produced 19k+ failed upgrades in a week (the Android client's auth plugin was demoting wss to https, arriving here as a plain GET). Log the error plus the upgrade-relevant request headers so a failing client is diagnosable from the server alone. Co-Authored-By: Claude Fable 5 --- internal/api/handlers/events_ws.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/internal/api/handlers/events_ws.go b/internal/api/handlers/events_ws.go index c771abf8..e22789a5 100644 --- a/internal/api/handlers/events_ws.go +++ b/internal/api/handlers/events_ws.go @@ -108,6 +108,21 @@ func (h *EventsHandler) HandleWebSocket(w http.ResponseWriter, r *http.Request) conn, err := wsUpgrader.Upgrade(w, r, nil) if err != nil { + // The Android/KMP client has a long history of silent handshake + // failures here (gorilla writes the 4xx itself); log the exact + // upgrade-relevant request shape so a failing client is diagnosable + // from the server alone. + slog.WarnContext(r.Context(), "events websocket upgrade failed", "component", "api", + "error", err, + "user_id", claims.UserID, + "proto", r.Proto, + "method", r.Method, + "connection_header", r.Header.Get("Connection"), + "upgrade_header", r.Header.Get("Upgrade"), + "ws_version", r.Header.Get("Sec-Websocket-Version"), + "ws_key_present", r.Header.Get("Sec-Websocket-Key") != "", + "user_agent", r.UserAgent(), + ) return } defer conn.Close()