What is EADDRINUSE?
Error: listen EADDRINUSE: address already in use :::3000 means another process is already listening on the port your application is trying to bind to. This is one of the most common errors in Node.js development.
The error code breaks down as:
- E - Error prefix
- ADDR - Address (the host + port combination)
- IN USE - Already occupied by another process
Quick Fix: One Command
The fastest way to fix EADDRINUSE is with portrm:
# Find and kill whatever is on port 3000
$ npx portrm fix 3000
# Or kill and restart your dev server in one step
$ npx portrm fix 3000 --run "npm run dev"
No need to look up PIDs, no risk of killing the wrong process. portrm identifies the service, checks if it is safe to kill, and handles the cleanup.
npx portrm runs without installing anything globally. Or install it once: npm i -g portrm
Why EADDRINUSE Happens
The most common causes:
1. A previous server did not shut down
You pressed Ctrl+C but the process is still running in the background. This happens frequently with tools that spawn child processes (Webpack, Vite, Next.js).
2. Hot reload created a zombie process
Your file watcher restarted the server but the old instance did not exit. Common with nodemon, ts-node-dev, and similar tools.
3. Another tool is using the port
Docker, another dev server, or a database is already bound to the port.
4. TIME_WAIT socket state
After a process exits, the OS keeps the port in TIME_WAIT for 30-60 seconds. This is less common but can cause issues during rapid restarts.
Framework-Specific Fixes
Express.js
# Error:
Error: listen EADDRINUSE: address already in use :::3000
# Fix:
$ ptrm fix 3000 --run "node server.js"
Prevention: add graceful shutdown to your Express app:
const server = app.listen(3000);
process.on('SIGTERM', () => server.close());
process.on('SIGINT', () => server.close());
Next.js
# Error:
ready - started server on 0.0.0.0:3000
Error: listen EADDRINUSE: address already in use :::3000
# Fix:
$ ptrm fix 3000 --run "npm run dev"
# Or use a different port:
$ npx next dev -p 3001
Vite
# Error:
Error: Port 5173 is already in use
# Fix:
$ ptrm fix 5173 --run "npm run dev"
Vite defaults to port 5173. You can change it in vite.config.ts:
export default defineConfig({
server: { port: 3000, strictPort: false }
});
Setting strictPort: false tells Vite to try the next available port instead of failing.
NestJS
# Fix:
$ ptrm fix 3000 --run "npm run start:dev"
Fastify
# Fix:
$ ptrm fix 3000 --run "node server.js"
Manual Fix by Operating System
macOS / Linux
# Find the process
$ lsof -i :3000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 1234 user 23u IPv6 ... 0t0 TCP *:3000
# Kill it
$ kill -9 1234
Windows
# Find the process
> netstat -ano | findstr :3000
TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 1234
# Kill it
> taskkill /PID 1234 /F
Preventing EADDRINUSE
1. Handle graceful shutdown
Always close your server on SIGTERM and SIGINT signals. This ensures the port is released when you stop the process.
2. Use portrm in your npm scripts
{
"scripts": {
"dev": "ptrm fix 3000 -y && next dev",
"predev": "ptrm fix 3000 -y"
}
}
3. Use a .ptrm.toml config
[project]
name = "my-app"
[services.frontend]
port = 3000
run = "npm run dev"
preflight = true
4. Set strictPort to false
Vite, Next.js, and other frameworks can auto-increment to the next available port instead of crashing.
Stop fighting EADDRINUSE
Install portrm and fix port conflicts in one command.