Introduction

WebSocket close code 1006 indicates an abnormal closure - the connection was closed without a proper close frame being sent. This means the connection was terminated unexpectedly, usually by a network intermediary (proxy, load balancer, firewall) or server crash rather than a clean application-level close:

javascript
websocket.onclose = (event) => {
    console.log(`WebSocket closed: code=${event.code} reason=${event.reason}`);
    // Output: WebSocket closed: code=1006 reason=""
};

Unlike codes 1000 (normal closure) or 1001 (going away), code 1006 provides no reason, making diagnosis challenging.

Symptoms

  • WebSocket disconnects randomly after a period of inactivity
  • event.code is 1006 with no reason provided
  • Real-time features (chat, live updates, notifications) stop working
  • Reconnecting manually restores functionality temporarily
  • Error occurs more frequently on mobile networks or behind corporate proxies

Common Causes

  • Nginx or Apache proxy timeout kills idle WebSocket connections (default 60s)
  • Load balancer health check or idle timeout terminates long-lived connections
  • Server process restarts without gracefully closing WebSocket connections
  • Network interruptions (WiFi switching, mobile data handoff)
  • Client goes to sleep (laptop lid close, mobile app backgrounding) breaking the TCP connection

Step-by-Step Fix

  1. 1.Configure Nginx proxy timeout for WebSocket:
  2. 2.```nginx
  3. 3.location /ws/ {
  4. 4.proxy_pass http://backend;
  5. 5.proxy_http_version 1.1;
  6. 6.proxy_set_header Upgrade $http_upgrade;
  7. 7.proxy_set_header Connection "upgrade";
  8. 8.proxy_set_header Host $host;
  9. 9.proxy_read_timeout 86400s;
  10. 10.proxy_send_timeout 86400s;
  11. 11.}
  12. 12.`
  13. 13.The 86400s (24 hours) timeout prevents Nginx from closing idle WebSocket connections.
  14. 14.Implement automatic reconnection with exponential backoff:
  15. 15.```javascript
  16. 16.function createWebSocket(url) {
  17. 17.let reconnectDelay = 1000;
  18. 18.const maxDelay = 30000;

function connect() { const ws = new WebSocket(url);

ws.onclose = (event) => { if (event.code === 1006 || event.code === 1001) { console.log(WebSocket disconnected (code ${event.code}). Reconnecting in ${reconnectDelay}ms...); setTimeout(() => { reconnectDelay = Math.min(reconnectDelay * 2, maxDelay); connect(); }, reconnectDelay); } };

ws.onopen = () => { reconnectDelay = 1000; // Reset delay on successful connection console.log('WebSocket connected'); };

return ws; }

return connect(); }

const ws = createWebSocket('wss://example.com/ws'); ```

  1. 1.Send periodic ping/pong keepalive messages to prevent idle timeout:
  2. 2.```javascript
  3. 3.// Client-side periodic message
  4. 4.const keepaliveInterval = setInterval(() => {
  5. 5.if (ws.readyState === WebSocket.OPEN) {
  6. 6.ws.send(JSON.stringify({ type: 'ping' }));
  7. 7.}
  8. 8.}, 30000); // Every 30 seconds

ws.onclose = () => clearInterval(keepaliveInterval); ```

  1. 1.Handle server-side ping responses (Node.js/Express with ws library):
  2. 2.```javascript
  3. 3.const WebSocket = require('ws');
  4. 4.const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', (ws) => { ws.isAlive = true; ws.on('pong', () => { ws.isAlive = true; }); ws.on('message', (data) => { const msg = JSON.parse(data); if (msg.type === 'ping') { ws.send(JSON.stringify({ type: 'pong' })); } }); });

// Check for dead connections every 30 seconds const interval = setInterval(() => { wss.clients.forEach((ws) => { if (!ws.isAlive) { ws.terminate(); return; } ws.isAlive = false; ws.ping(); }); }, 30000); ```

Prevention

  • Always implement automatic reconnection with exponential backoff for WebSocket clients
  • Configure proxy timeouts to exceed the expected maximum WebSocket connection duration
  • Use ping/pong keepalive messages at intervals shorter than the lowest proxy timeout
  • Monitor WebSocket disconnect rates and correlate with server deployments
  • Use ws.readyState checks before sending messages to avoid errors on closed connections
  • Test WebSocket stability behind various proxy configurations (Nginx, HAProxy, AWS ALB) during development
  • Consider using a WebSocket library with built-in reconnection (Socket.IO, Pusher) for production applications