Node.js Error EADDRINUSE: Address already in use
Another process already listens on that port, often a previous dev server that did not exit. Kill it (lsof -ti :3000 | xargs kill) or use a different PORT, and close the server on SIGTERM.
Identify: does your log match?
node:events:497
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE: address already in use :::3000
at Server.setupListenHandle [as _listen2] (node:net:1904:16)
at listenInCluster (node:net:1952:12)
at Server.listen (node:net:2063:7) {
code: 'EADDRINUSE',
errno: -98,
syscall: 'listen',
address: '::',
port: 3000
}- High
Orphaned previous dev server
A crashed terminal, nodemon restart or IDE run left the old process alive and holding the port.
- Medium
listen() called twice
Importing the app module twice, or calling app.listen in both server.ts and a test, binds the same port twice in one process.
- Medium
Another service owns the port
macOS AirPlay Receiver uses 5000 and 7000; Docker containers publish ports on the host.
Fix
Find and stop the process holding the port
npm run dev # EADDRINUSE againlsof -nP -iTCP:3000 -sTCP:LISTEN kill $(lsof -ti tcp:3000) # SIGTERM; use kill -9 only if it ignores it # Windows: netstat -ano | findstr :3000 then taskkill /PID <pid> /F
lsof shows the PID and command name so you do not kill the wrong process.
Verify: reproduce it on purpose
$ node -e "const n=require('net');n.createServer().listen(3000,()=>n.createServer().listen(3000).on('error',e=>{console.log(e.code);process.exit()}))"Run it against a dev environment to trigger EADDRINUSE on purpose and test your error handler.
Prevent
- Read PORT from env.
- Use supertest(app) instead of listening in tests.
- Handle SIGTERM in every long-running process.
FAQ
Why is port 5000 taken on my Mac?
macOS Monterey+ runs AirPlay Receiver on 5000 and 7000. Disable it in System Settings > General > AirDrop & Handoff or use another port.
Can I make the OS pick a free port?
Yes, listen(0) binds a random free port; read it with server.address().port.
What does ::: in "address already in use :::3000" mean?
It is the IPv6 wildcard :: followed by :3000, meaning Node tried to listen on all interfaces.
Related errors
Last verified 2026-10-20 · Source: POSIX errno + Node.js ERR_* codes (doc/api/errors.md) · Official docs ↗ · ~22,200 searches/mo