426 medium
426 Upgrade Required
The server refuses the request on the current protocol and demands an upgrade, almost always a broken WebSocket handshake through a proxy.
What you see
426 Upgrade Required Upgrade: websocket (in DevTools Console) WebSocket connection to 'wss://example.com/socket' failed: Error during WebSocket handshake: Unexpected response code: 426
What’s actually happening
A page loads fine over HTTP but the live features (chat, notifications, a dashboard that streams updates) never connect. Open DevTools and the Network tab shows the wss:// request finishing with status 426 instead of 101 Switching Protocols. The server is saying "I won't talk to you on plain HTTP/1.0, switch protocols first" but the upgrade never completes because something between the client and the app server ate the handshake headers.
Common causes
- Nginx (or another reverse proxy) not forwarding the Upgrade and Connection headers to the backend, so the app never sees a WebSocket request.
- proxy_http_version left at the default 1.0 in Nginx, which can't carry a WebSocket upgrade. It needs 1.1.
- A load balancer or CDN layer that doesn't have WebSocket support enabled for the route.
- The backend app explicitly requiring a protocol the client isn't offering (e.g. an API that mandates HTTP/2 or TLS 1.2+ and returns 426 to anything older).
- A WebSocket library version mismatch where the client and server negotiate incompatible subprotocols.
How to fix it
- Add the upgrade headers to your Nginx location blockIn the location that proxies the socket: proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; Reload with nginx -s reload. Without all three the handshake dies at the proxy and the backend returns 426.
- Confirm the request actually reaches the backendTail the app log while you reload the page. If you see the WebSocket route get hit, the proxy is forwarding correctly and the problem is in the app. If you see nothing, the proxy is swallowing it, go back to fix #1.
- Enable WebSocket support on the load balancer / CDNAWS ALB needs the target group on HTTP/1.1; Cloudflare needs WebSockets toggled on (Network tab in the dashboard). On Apache as a proxy, load mod_proxy_wstunnel and route wss traffic through it.
- Read the Upgrade header the server sent backcurl -i the endpoint and look at the Upgrade: response header. It tells you exactly which protocol the server wants. If it says TLS/1.2 or HTTP/2, this is a protocol-policy 426, not a WebSocket issue, and you fix it by raising the client's TLS/HTTP version.
- Match client and server WebSocket versionsPin socket.io / ws (or your stack's equivalent) to versions known to interoperate. A v2 client against a v4 server will fail the handshake even when the proxy is perfect.
Stop it recurring
Bake the three proxy_set_header / proxy_http_version 1.1 lines into your Nginx template so every new WebSocket route inherits them.
Related errors