🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

How to Fix EADDRINUSE Port Already in Use Error in Node.js

⏱️3 min read  ·  592 words

The error Error: listen EADDRINUSE: address already in use :::3000 means another process is already using the port your Node.js app wants. It’s one of the most common errors during development. Here’s every way to fix it.

What Causes This Error

  • A previous server instance didn’t shut down cleanly and still holds the port
  • Another application is using the same port (another dev server, database)
  • A crashed process left a zombie holding the port
  • You started your server twice

Fix 1: Find and Kill the Process (macOS/Linux)

# Find the process using port 3000
lsof -i :3000
# COMMAND   PID  USER   FD   TYPE  DEVICE  NODE NAME
# node    12345  you   20u  IPv6  ...     TCP  *:3000 (LISTEN)

# Kill it by PID
kill -9 12345

# Or do it in one command
kill -9 $(lsof -ti :3000)

# Kill all node processes (nuclear option)
killall -9 node

Fix 2: Find and Kill the Process (Windows)

# Find the process using port 3000
netstat -ano | findstr :3000
# TCP    0.0.0.0:3000    0.0.0.0:0    LISTENING    12345

# Kill it by PID
taskkill /PID 12345 /F

# PowerShell one-liner
Stop-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess -Force

Fix 3: Use a Different Port

// Make the port configurable via environment variable
const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log("Server running on port " + PORT);
});

// Then run with a different port:
// PORT=3001 node server.js

Fix 4: Handle the Error Gracefully

const server = app.listen(PORT);

server.on('error', (err) => {
  if (err.code === 'EADDRINUSE') {
    console.error("Port " + PORT + " busy. Trying " + (PORT + 1));
    server.listen(PORT + 1);  // fall back to next port
  } else {
    throw err;
  }
});

Fix 5: Implement Graceful Shutdown (Prevents the Problem)

The root cause is often a server that does not release the port on exit. Add graceful shutdown handlers:

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

function shutdown(signal) {
  console.log(signal + " received. Closing server...");
  server.close(() => {
    console.log("Server closed. Port released.");
    process.exit(0);
  });
  setTimeout(() => {
    console.error("Forced shutdown");
    process.exit(1);
  }, 10000);
}

process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));  // Ctrl+C

Fix 6: Use nodemon for Clean Restarts

npm install --save-dev nodemon

# package.json
{
  "scripts": {
    "dev": "nodemon server.js"
  }
}

# nodemon cleanly restarts and releases ports between reloads
npm run dev

Reusable Kill-Port Script

# kill-port.sh
#!/bin/bash
PORT=${1:-3000}
PID=$(lsof -ti :$PORT)
if [ -n "$PID" ]; then
  echo "Killing process $PID on port $PORT"
  kill -9 $PID
else
  echo "No process on port $PORT"
fi

# Usage: ./kill-port.sh 3000

Frequently Asked Questions

Q: Why does the port stay in use after I stop my app?
A: Usually because the process was killed abruptly without releasing the socket, or a child process still holds it. Graceful shutdown handlers prevent this.

Q: What does ::: in ‘:::3000’ mean?
A: IPv6 notation for “all interfaces” (like 0.0.0.0 in IPv4). Your server binds to all network interfaces on port 3000.

Q: Can two apps share the same port?
A: No — only one process can bind to a port on an interface at a time. Use different ports or a reverse proxy (nginx) to route by path/domain.

Q: How do I avoid this in Docker?
A: Each container has its own network namespace, so conflicts only happen at host mapping. Map different host ports: -p 3001:3000.

Q: Is killall node safe?
A: It kills ALL Node.js processes — fine in development, but careful if you have other Node apps you don’t want stopped.

Conclusion

EADDRINUSE means the port is already taken. Quick fix: find the process with lsof -ti :PORT and kill it. Permanent fix: add graceful shutdown handlers so your server always releases the port on exit, and use nodemon in development for clean restarts. Making the port configurable via process.env.PORT also sidesteps conflicts instantly.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা