Error: listen EADDRINUSE: address already in use :::3000 — how to fix
node:events:497
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE: address already in use :::3000
at Server.setupListenHandle [as _listen2] (node:net:1817:16)
at listenInCluster (node:net:1865:12)
at Server.listen (node:net:1953:7)
Emitted 'error' event on Server instance at:
code: 'EADDRINUSE',
errno: -98,
syscall: 'listen',
address: '::',
port: 3000
Quick fix: Find the process: lsof -i :3000 (macOS/Linux) or netstat -ano | findstr :3000 (Windows), then kill it: kill <PID> / taskkill /PID <PID> /F. Or one-liner: npx kill-port 3000. Alternatively start on another port: PORT=3001 npm start.
What it means
Only one socket can listen on a given address and port. EADDRINUSE (errno 98 on Linux, 48 on macOS) means something else got there first. :::3000 means Node tried to listen on all IPv6 (and usually IPv4) addresses on port 3000.
Fix 1: find and stop the process using the port
macOS / Linux:
lsof -i :3000 # shows COMMAND and PID
kill <PID> # polite
kill -9 <PID> # if it won't die
# or in one go:
kill $(lsof -t -i :3000)
On Linux without lsof: sudo ss -ltnp | grep :3000 or sudo fuser -k 3000/tcp.
Windows (cmd / PowerShell):
netstat -ano | findstr :3000
taskkill /PID 12345 /F
PowerShell: Get-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess | Stop-Process.
Cross-platform:
npx kill-port 3000
Cause 1: an old dev server is still running
Common situations:
- You closed a terminal tab but the
node/nodemonprocess kept running. - You pressed
Ctrl+Zinstead ofCtrl+C— that suspends the process, it still holds the port. RunfgthenCtrl+C, orkill %1. - VS Code's debugger or a second terminal is running the same app.
Cause 2: nodemon restarts too fast
On restart, nodemon may start the new process before the old one releases the port. Make sure the old server shuts down cleanly:
const server = app.listen(PORT);
process.once('SIGUSR2', () => server.close(() => process.kill(process.pid, 'SIGUSR2')));
process.on('SIGINT', () => server.close(() => process.exit(0)));
process.on('SIGTERM', () => server.close(() => process.exit(0)));
If you call app.listen() twice in your code (e.g. once in app.js and once in server.js, or in a test file that imports the app), the second call fails with this error. Export the app and call listen in one place only.
Cause 3: another program uses that port
Port 3000 (other dev servers), 5000 (macOS AirPlay Receiver since Monterey), 8080 (Tomcat, proxies) and 5432/3306 (databases) are commonly taken. On macOS, disable AirPlay Receiver in System Settings → General → AirDrop & Handoff, or just pick another port.
Fix 2: make the port configurable
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Listening on ${PORT}`));
PORT=3001 npm start # macOS/Linux
set PORT=3001 && npm start # Windows cmd
Fix 3: handle the error gracefully
const server = app.listen(PORT);
server.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error(`Port ${PORT} is in use. Stop the other process or set PORT.`);
process.exit(1);
}
throw err;
});
Docker
If the port is published by a container (docker ps shows 0.0.0.0:3000->3000/tcp), stop it with docker stop <container> or map a different host port: -p 3001:3000.
Last updated 2026-11-03.