error nodejs

Node.js EADDRINUSE

Understanding Node.js EADDRINUSE error - the port is already in use by another process, preventing the server from starting.

What It Means

EADDRINUSE means “Error: Address Already In Use.” This occurs when your Node.js application tries to listen on a port that is already being used by another process. The full error message is typically: listen EADDRINUSE: address already in use :::3000.

Common Causes

  • Another instance of your application is already running
  • A previous process crashed but didn’t release the port
  • Another application is using the same port
  • Nodemon or PM2 restarted the app before the old process fully closed
  • Docker mapped the port and it’s still in use
  • Development server from another project is running

How to Fix

Find and kill the process using the port

# Find what's using port 3000
lsof -i :3000
# or
ss -tlnp | grep 3000
# or (on macOS)
lsof -ti :3000

# Kill the process
kill $(lsof -ti :3000)

# Force kill if needed
kill -9 $(lsof -ti :3000)

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

Use a different port

const PORT = process.env.PORT || 3000;

const server = app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

server.on('error', (error) => {
  if (error.code === 'EADDRINUSE') {
    console.error(`Port ${PORT} is already in use.`);
    console.log(`Try: PORT=${PORT + 1} node app.js`);
    process.exit(1);
  }
});

Auto-find an available port

const net = require('net');

function getAvailablePort(startPort = 3000) {
  return new Promise((resolve, reject) => {
    const server = net.createServer();
    server.unref();
    server.on('error', (err) => {
      if (err.code === 'EADDRINUSE') {
        resolve(getAvailablePort(startPort + 1));
      } else {
        reject(err);
      }
    });
    server.listen(startPort, () => {
      const { port } = server.address();
      server.close(() => resolve(port));
    });
  });
}

// Usage
const port = await getAvailablePort(3000);
app.listen(port, () => console.log(`Server on port ${port}`));

Graceful shutdown to release port

const server = app.listen(3000);

function gracefulShutdown() {
  console.log('Shutting down gracefully...');
  server.close(() => {
    console.log('Server closed');
    process.exit(0);
  });

  // Force close after 10s
  setTimeout(() => process.exit(1), 10000);
}

process.on('SIGTERM', gracefulShutdown);
process.on('SIGINT', gracefulShutdown);

Fix with nodemon

{
  "scripts": {
    "dev": "nodemon --signal SIGTERM app.js"
  }
}

Fix SO_REUSEADDR

const server = app.listen(3000);

// Allow port reuse (helps with rapid restarts)
server.on('error', (e) => {
  if (e.code === 'EADDRINUSE') {
    console.log('Port in use, retrying in 1 second...');
    setTimeout(() => {
      server.close();
      server.listen(3000);
    }, 1000);
  }
});