Fix WebSocket Connection Failures in Claude Code
Your application uses WebSockets and the connection fails with errors like:
WebSocket connection to 'ws://localhost:3001' failed:
Error during WebSocket handshake: Unexpected response code: 400
Or in your server logs:
Error: listen EADDRINUSE :::3001
WebSocket: Invalid frame header
Quick Fix
Check the three most common causes:
# 1. Is the WS server running?
lsof -i :3001
# 2. Is the client connecting to the right URL?
grep -r "ws://" src/ --include="*.ts" --include="*.js"
# 3. Is a proxy interfering?
cat vite.config.ts
If using a dev server with a proxy, add WebSocket proxy support:
// vite.config.ts
export default defineConfig({
server: {
proxy: {
'/ws': {
target: 'ws://localhost:3001',
ws: true,
},
},
},
});
What Is Happening
WebSocket connections start as HTTP requests that "upgrade" to the WebSocket protocol. This upgrade handshake is where most failures occur. Common causes include:
- Missing upgrade handling: The server does not handle the HTTP upgrade request
- Proxy stripping headers: A reverse proxy or dev server strips the
UpgradeandConnectionheaders - CORS blocking: The server rejects the WebSocket origin
- Port mismatch: Client connects to the wrong port or the server is not listening
- SSL/TLS mismatch: Using
ws://when the page is served over HTTPS (requireswss://)
Step-by-Step Fix
Step 1: Verify the server setup
A correct Node.js WebSocket server looks like:
import { WebSocketServer } from 'ws';
import { createServer } from 'http';
const server = createServer();
const wss = new WebSocketServer({ server });
wss.on('connection', (ws) => {
console.log('Client connected');
ws.on('message', (data) => {
ws.send(JSON.stringify({ echo: data.toString() }));
});
});
server.listen(3001, () => {
console.log('WebSocket server running on port 3001');
});
Step 2: Fix the client connection
// Auto-detect protocol
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const ws = new WebSocket(\`\${protocol}//\${window.location.host}/ws\`);
Step 3: Configure proxy for development
Next.js:
// next.config.js
module.exports = {
async rewrites() {
return [{ source: '/ws', destination: 'http://localhost:3001/ws' }];
},
};
Step 4: Add reconnection logic
WebSocket connections drop. Production code needs automatic reconnection with exponential backoff:
class ReconnectingWebSocket {
private ws: WebSocket | null = null;
private reconnectAttempts = 0;
private maxReconnectAttempts = 10;
private baseDelay = 1000;
constructor(private url: string) { this.connect(); }
private connect(): void {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => { this.reconnectAttempts = 0; };
this.ws.onclose = () => {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
const delay = this.baseDelay * Math.pow(2, this.reconnectAttempts);
this.reconnectAttempts++;
setTimeout(() => this.connect(), delay);
}
};
}
}
Prevention
Test WebSocket connections with wscat before integrating with your frontend:
npx wscat -c ws://localhost:3001/ws
Paste your error into our Error Diagnostic for an instant fix.
Master Claude Code
Get lifetime access to all ClaudHQ tools, advanced workflows, and production-grade templates.
Get Lifetime AccessWritten by the ClaudHQ team ยท Expert Claude Code guides and tools