WebSocket connection failed through Nginx (missing Upgrade headers) Nginx / Apache Origin: Edge & web server Last updated 5 Nov 2026

Browser: WebSocket connection to 'wss://example.com/socket' failed: Error during WebSocket handshake: Unexpected response code: 400 (nginx proxy)

Nginx isn't forwarding the Upgrade/Connection headers needed for WebSockets.

Exact message you may see WebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 400 nginxWebSocket connection to wss:// failed nginx proxy Upgrade headerWebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 200nginx websocket 502 Bad Gateway upgradeSocket.IO behind nginx 400 Bad Request
Seen on: Nginx JavaScript

Meaning

Add to the proxy location: proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; and raise proxy_read_timeout so idle sockets aren't closed. Socket.IO, Vite HMR, Next.js dev and ActionCable need this.

Common causes

  • Missing proxy_set_header Upgrade / Connection
  • HTTP/1.0 proxying (default)
  • proxy_read_timeout too short (60s)
  • Wrong location path
  • CDN/load balancer not allowing WebSockets

⚡ Quick fix

  1. Add the Upgrade/Connection headers and proxy_http_version 1.1;
  2. Increase proxy_read_timeout 3600s;
  3. Verify CDN/ALB WebSocket support

Detailed fix by platform

Nginx

  1. location /socket { proxy_pass http://app; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; }

How to diagnose

  1. Headers — Upgrade forwarded?
  2. HTTP version — 1.1?
  3. Timeout — Long enough?

🔧 Still not fixed?

Many errors look alike. If the steps above didn’t solve it, one of these is probably what you’re facing:

Where this error sits

Origin: Edge & web server. Errors that are often confused with or caused by this one (click to open):

400 — HTTP 400 Bad Request (HTTP)400Cloudflare 502 — Cloudflare-branded 502 Bad Gateway / 504 Gateway Timeout ("cloudflare" footer) (Cloudflare)Cloudflare 502connect() failed (111: Connection refused) while connecting to upstream — Nginx: [error] connect() failed (111: Connection refused) while connecting to upstream, upstream: "http://127.0.0.1:3000/" (Nginx / Apache)connect() failed (111…no resolver defined to resolve example.com — Nginx: [error] no resolver defined to resolve api.example.com, client: 203.0.113.5 (502 when proxy_pass uses a variable) (Nginx / Apache)no resolver defined t…proxy_pass with a URI changes the path (404 from upstream) — Nginx: reverse proxy returns 404 — location /api/ { proxy_pass http://app:3000/; } strips the prefix (or keeps it) (Nginx / Apache)proxy_pass with a URI…SSL_do_handshake() failed while SSL handshaking to upstream — Nginx: [error] SSL_do_handshake() failed (SSL: error:0A000410:SSL routines::sslv3 alert handshake failure) while SSL handshaking to upstream (Nginx / Apache)SSL_do_handshake() fa…upstream sent too big header while reading response header — Nginx: [error] upstream sent too big header while reading response header from upstream (502 Bad Gateway) (Nginx / Apache)upstream sent too big…WebSocket…

Explore the map of this error Full error map →

🧠 Still stuck? Analyze your error

Paste the full message, response headers or stack trace — we'll detect the platform and point to the most likely cause.

💬 What worked for others

No tips yet — did something else fix this for you?

Share what worked for you

Tips are checked by an editor before they appear. Links are removed.