Introduction

The EADDRINUSE error occurs when Node.js tries to listen on a port that is already bound by another process. This commonly happens when a previous instance of the application did not shut down cleanly, when running multiple instances, or when another service uses the same port.

This is one of the most common startup errors in Node.js development and production.

Symptoms

  • Node.js crashes with "Error: listen EADDRINUSE: address already in use :::3000"
  • Application fails to start after a crash or restart
  • Error shows the specific port that is already in use

Common Causes

  • Previous Node.js process is still running (zombie process from hot-reload)
  • Another service is using the same port
  • Application restarts faster than the OS releases the port (TIME_WAIT state)

Step-by-Step Fix

  1. 1.Find and kill the process using the port: Identify what is occupying the port.
  2. 2.```bash
  3. 3.# Linux/macOS - find process on port 3000:
  4. 4.lsof -i :3000
  5. 5.# Output:
  6. 6.# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
  7. 7.# node 12345 user 22u IPv6 12345 0t0 TCP *:3000 (LISTEN)

# Kill the process: kill 12345

# Or force kill if it doesn't respond: kill -9 12345

# Alternative using fuser: fuser -k 3000/tcp

# Windows: netstat -ano | findstr :3000 taskkill /PID <PID> /F ```

  1. 1.Enable SO_REUSEADDR for faster restarts: Allow port reuse during TIME_WAIT.
  2. 2.```javascript
  3. 3.const http = require('http');
  4. 4.const net = require('net');

const server = http.createServer(app);

// Enable address reuse before listening: server.on('listening', () => { console.log('Server is running on port 3000'); });

server.on('error', (err) => { if (err.code === 'EADDRINUSE') { console.error('Port 3000 is already in use'); process.exit(1); } });

server.listen(3000); ```

  1. 1.Use a dynamic port in development: Fall back to an available port.
  2. 2.```javascript
  3. 3.const PORT = process.env.PORT || 3000;

server.listen(PORT, () => { console.log(Server running on port ${PORT}); }).on('error', (err) => { if (err.code === 'EADDRINUSE') { const fallbackPort = PORT + 1; console.log(Port ${PORT} in use, trying ${fallbackPort}); server.listen(fallbackPort); } }); ```

Prevention

  • Use process managers like PM2 that handle graceful restarts: pm2 restart app
  • Add a pre-start script that kills existing processes on the target port
  • Use Docker port mapping to avoid host port conflicts
  • Implement graceful shutdown with server.close() to release ports promptly