Fix 'EADDRINUSE: address already in use' Error When Starting Node.js Server

beginner๐Ÿ’š Node.js2026-03-18| Node.js (all versions), macOS / Linux / Windows

Error Message

Error: listen EADDRINUSE: address already in use :::3000
#Node.js#EADDRINUSE#port

The Error

Error: listen EADDRINUSE: address already in use :::3000
    at Server.setupListenHandle [as _listen2] (node:net:1739:16)
    at listenInCluster (node:net:1787:12)
    at Server.listen (node:net:1875:7)
    at Function.listen (/app/node_modules/express/lib/application.js:635:24)

Port 3000 is taken. Node.js tried to bind a listener there, found something already running, and bailed out. Two processes cannot share the same TCP port โ€” so one of them has to go.

Root Cause

Three common culprits:

  • A previous server instance crashed or you force-closed the terminal window. The Node.js process kept running in the background, still holding port 3000.
  • Something else already claimed that port โ€” a different Node.js app, Webpack dev server, a Python Flask app, you name it.
  • You restarted too fast. The OS needs a moment (usually a few seconds) to reclaim a port after the old process exits. Hit Ctrl+C and immediately ran npm start? You might have beaten the clock.

Step-by-Step Fix

Step 1: Find the process using the port

On macOS / Linux:

lsof -i :3000

Example output:

COMMAND   PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node     1234  alice   23u  IPv6  12345      0t0  TCP *:3000 (LISTEN)

That PID column โ€” 1234 here โ€” is what you need in the next step.

Prefer ss or netstat? Those work too:

# Using ss
ss -tlnp | grep :3000

# Using netstat
netstat -tlnp | grep :3000

On Windows (Command Prompt or PowerShell):

netstat -ano | findstr :3000

Example output:

TCP    0.0.0.0:3000    0.0.0.0:0    LISTENING    5678

The last number (5678) is the PID.

Step 2: Kill the process

On macOS / Linux:

kill -9 1234

Swap 1234 for the actual PID you found. Or skip the lookup entirely and do it in one shot:

kill -9 $(lsof -ti :3000)

On Windows (run as Administrator):

taskkill /PID 5678 /F

Step 3: Restart your Node.js server

node app.js
# or
npm start
# or
npx ts-node src/index.ts

Alternative Fix: Use a Different Port

Maybe the process on port 3000 is intentional โ€” another app you need running. No problem. Just move your server elsewhere.

In your app code:

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

Or set the port at startup without touching your code:

PORT=3001 node app.js

On Windows:

set PORT=3001 && node app.js

Fix for nodemon / Development Watch Mode

Seeing this error after every file save? nodemon is probably restarting the process before the OS has reclaimed the port. A 1-second delay usually fixes it:

# nodemon.json
{
  "delay": 1000
}

If it's really stuck, nuke all Node processes and start fresh:

# macOS / Linux โ€” kill all Node processes
pkill -f node

# then restart
npm run dev

Verify the Fix

Run the same lookup command after killing the process:

# macOS / Linux
lsof -i :3000

# Windows
netstat -ano | findstr :3000

No output means the port is free. Start your server โ€” it should come up clean.

Want to confirm it's actually responding? Run a quick curl:

curl http://localhost:3000
# or open http://localhost:3000 in a browser

Tips to Avoid This Error

  • Ctrl+C beats closing the terminal โ€” closing the window often orphans the Node.js process. It keeps running, keeps holding the port. Ctrl+C sends SIGINT and shuts things down properly.
  • Read the port from an env variable โ€” hardcoding 3000 works until it doesn't. process.env.PORT || 3000 lets you switch ports with a single env var, no code edits needed.
  • Add a graceful shutdown handler in production โ€” this lets the server release the port cleanly on exit:
process.on('SIGTERM', () => {
  server.close(() => {
    console.log('Server closed');
    process.exit(0);
  });
});
  • Using PM2? Mind the old instance โ€” pm2 restart app handles overlap automatically. For a fresh start, run pm2 stop all first to make sure nothing is still clinging to your port.

Related Error Notes