Back to Tools

Fix "EADDRINUSE: Address Already in Use" in Node.js

Kill any port on Mac, Linux, and Windows — and prevent it from happening again

The EADDRINUSE error means the port you are trying to use is already occupied by another process. This guide covers the fastest way to kill the blocking process on every OS, plus how to prevent this error permanently.

The Error Message

What you see in the terminal:

Error: listen EADDRINUSE: address already in use :::3000
    at Server.setupListenHandle [as _listen2] (net.js:1318:16)
    at listenInCluster (net.js:1366:12)
    at Server.listen (net.js:1452:7)
    at Function.listen (/app/node_modules/express/lib/application.js:618:24)
    at Object.<anonymous> (/app/server.js:10:5)

Port 3000 in the error can be any port — 4000, 8080, 5173, or whatever your app uses.

Fix on Mac / Linux

Three commands — from fastest to most explicit:

Option 1: One-liner (fastest)

Kill port 3000 in one command:

lsof -ti:3000 | xargs kill -9

# For port 8080:
lsof -ti:8080 | xargs kill -9

lsof -ti:3000 outputs just the PID, which is piped directly to kill -9.

Option 2: Find PID first, then kill

Two-step approach — see what is running first:

# Step 1: Find the process
lsof -i :3000
# Output:
# COMMAND   PID   USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
# node    12345   john   23u  IPv6  ...          3000 (LISTEN)

# Step 2: Kill it using the PID
kill -9 12345

Option 3: fuser (Linux only)

Linux alternative using fuser:

# Kill all processes on TCP port 3000
fuser -k 3000/tcp

# Verbose output (shows PIDs before killing)
fuser -v -k 3000/tcp

Fix on Windows

Find and kill with netstat + taskkill:

# Step 1: Find which process uses port 3000
netstat -ano | findstr :3000
# Output:
#   TCP    0.0.0.0:3000    0.0.0.0:0    LISTENING    12345

# Step 2: Kill the process by PID (12345 in this example)
taskkill /PID 12345 /F

# Or kill by process name:
taskkill /IM node.exe /F

Run Command Prompt or PowerShell as Administrator if you get permission errors.

Add npx kill-port to package.json Scripts

The kill-port package works on all platforms (Mac, Linux, Windows) and can be chained into your start script so the port is always freed before your server launches.

package.json — auto-kill port on start:

{
  "scripts": {
    "dev": "npx kill-port 3000 && node server.js",
    "start": "npx kill-port 3000 && node server.js",
    "kill": "npx kill-port 3000"
  }
}

# Now: npm run dev will always free port 3000 first
# Or kill manually: npm run kill

Automatically Use Next Free Port

Instead of hardcoding a port, use the portfinder package to automatically find and bind to the next available port.

Auto-select next free port:

// npm install portfinder
const portfinder = require('portfinder');
const express = require('express');
const app = express();

portfinder.basePort = 3000; // start searching from 3000

portfinder.getPortPromise()
  .then((port) => {
    app.listen(port, () => {
      console.log(`Server running on http://localhost:${port}`);
    });
  })
  .catch((err) => {
    console.error('Could not find a free port:', err);
  });

Prevent It: Use process.on('SIGTERM') for Graceful Shutdown

The most permanent fix is ensuring your server always releases the port when it exits. This prevents zombie processes from accumulating.

Graceful shutdown — always release the port:

const server = app.listen(3000, () => {
  console.log('Server running on port 3000');
});

function shutdown(signal) {
  console.log(`Received ${signal}, shutting down gracefully...`);
  server.close(() => {
    console.log('Port released. Process exiting.');
    process.exit(0);
  });

  // Force exit if close takes too long
  setTimeout(() => process.exit(1), 5000);
}

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

Why Does This Happen?

  • Server crashed mid-run — unhandled exception exits the process without releasing the port
  • Ctrl+C timing — the port enters TCP TIME_WAIT state briefly after a fast kill
  • Multiple dev servers — running npm run dev twice without stopping the first one
  • Hot-reloader re-bind race — nodemon or ts-node-dev restarting before the old socket fully closes
  • Docker containers — a stopped container still holding the port binding on the host

Debug your API requests with our HAR to cURL tool →

Convert browser HAR exports to cURL commands you can run from any terminal.

Frequently Asked Questions

What causes EADDRINUSE in Node.js?

Another process is already listening on that port. Common causes include a crashed server that did not release the port, or running two instances of your dev server simultaneously.

How do I kill port 3000 on Mac?

Run lsof -ti:3000 | xargs kill -9 in your terminal. This works for any port — replace 3000 with your port number.

How do I kill a port on Windows?

Run netstat -ano | findstr :3000 to get the PID, then taskkill /PID <pid> /F. Or use npx kill-port 3000.

How can I automatically find the next available port?

Use the portfinder package. Call portfinder.getPortPromise() to get the next free port from your base port.

Why does the port stay in use after stopping my server?

Without a graceful shutdown handler, the OS may keep the port in TIME_WAIT state. Implement process.on('SIGINT') to call server.close() before exiting.

Related Tools