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:
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.codeis 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.Configure Nginx proxy timeout for WebSocket:
- 2.```nginx
- 3.location /ws/ {
- 4.proxy_pass http://backend;
- 5.proxy_http_version 1.1;
- 6.proxy_set_header Upgrade $http_upgrade;
- 7.proxy_set_header Connection "upgrade";
- 8.proxy_set_header Host $host;
- 9.proxy_read_timeout 86400s;
- 10.proxy_send_timeout 86400s;
- 11.}
- 12.
` - 13.The 86400s (24 hours) timeout prevents Nginx from closing idle WebSocket connections.
- 14.Implement automatic reconnection with exponential backoff:
- 15.```javascript
- 16.function createWebSocket(url) {
- 17.let reconnectDelay = 1000;
- 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.Send periodic ping/pong keepalive messages to prevent idle timeout:
- 2.```javascript
- 3.// Client-side periodic message
- 4.const keepaliveInterval = setInterval(() => {
- 5.if (ws.readyState === WebSocket.OPEN) {
- 6.ws.send(JSON.stringify({ type: 'ping' }));
- 7.}
- 8.}, 30000); // Every 30 seconds
ws.onclose = () => clearInterval(keepaliveInterval); ```
- 1.Handle server-side ping responses (Node.js/Express with ws library):
- 2.```javascript
- 3.const WebSocket = require('ws');
- 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.readyStatechecks 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