gofr-dev/gofr · error
Could not open WebSocket connection
Error message
Could not open WebSocket connection
What it means
The WebSocket middleware returns HTTP 400 with the body 'Could not open WebSocket connection' when gorilla's Upgrade() fails while handling an upgrade request. This happens when the request does not meet WebSocket handshake requirements or the underlying connection cannot be hijacked. It is an HTTP response, not a Go error value.
Source
Thrown at pkg/gofr/http/middleware/web_socket.go:21
import (
"context"
"net/http"
gorillaWebsocket "github.com/gorilla/websocket"
"gofr.dev/pkg/gofr/container"
"gofr.dev/pkg/gofr/websocket"
)
// WSHandlerUpgrade middleware upgrades the incoming http request to a websocket connection using websocket upgrader.
func WSHandlerUpgrade(c *container.Container, wsManager *websocket.Manager) func(inner http.Handler) http.Handler {
return func(inner http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if gorillaWebsocket.IsWebSocketUpgrade(r) {
conn, err := wsManager.WebSocketUpgrader.Upgrade(w, r, nil)
if err != nil {
c.Errorf("Failed to upgrade to WebSocket: %v", err)
http.Error(w, "Could not open WebSocket connection", http.StatusBadRequest)
return
}
// Add the connection to the hub
wsManager.AddWebsocketConnection(r.Header.Get("Sec-WebSocket-Key"), &websocket.Connection{Conn: conn})
// Store the websocket connection key in the context
ctx := context.WithValue(r.Context(), websocket.WSConnectionKey, r.Header.Get("Sec-WebSocket-Key"))
r = r.WithContext(ctx)
}
inner.ServeHTTP(w, r)
})
}
}
View on GitHub (pinned to 187eb24962)
Solutions
- Ensure the client sends a valid RFC 6455 handshake (Upgrade: websocket, Connection: Upgrade, Sec-WebSocket-Key, Sec-WebSocket-Version: 13)
- Serve the app over HTTP/1.1 and confirm the server/proxy supports connection upgrade; add proxy headers (e.g. proxy_set_header Upgrade/Connection in nginx)
- Check server logs for the 'Failed to upgrade to WebSocket: %v' line to see the underlying upgrade error
Example fix
// before (nginx)
location /ws { proxy_pass http://backend; }
// after (nginx)
location /ws {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
} Defensive patterns
Strategy: try-catch
Validate before calling
if !gorillaWebsocket.IsWebSocketUpgrade(r) || r.Header.Get("Sec-WebSocket-Key") == "" || r.Header.Get("Sec-WebSocket-Version") != "13" { http.Error(w, "invalid handshake", http.StatusBadRequest); return } Try / catch
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
logger.Errorf("upgrade failed: %v", err)
http.Error(w, "Could not open WebSocket connection", http.StatusBadRequest)
return
} Prevention
- Serve WebSockets over HTTP/1.1 only; disable HTTP/2 for WS routes
- Configure reverse proxies to forward Upgrade/Connection headers
- Check server logs for the underlying upgrade error message
When it happens
Trigger: Client sends a WebSocket upgrade request missing required headers (Sec-WebSocket-Key, Sec-WebSocket-Version, valid Upgrade/Connection); request passes through a proxy that strips headers; response headers already written (HTTP/2 or buffering) preventing connection hijack.
Common situations: Browsers/clients behind corporate proxies that mangle upgrade requests; serving WebSockets over HTTP/2 or through servers that don't support hijacking; ad-blocking proxies interfering with the handshake.
Related errors
- response writer does not support hijacking
- %w: cannot hijack connection
- response body is empty
- %w: creating index: %w
- %w: deleting index: %w
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/7e5fd5c582740b73.
Report an issue: GitHub.