EADDRINUSE: address already in use :::3000 / 0.0.0.0:8080
Your server tried to open a port and the operating system said someone is already sitting there. Nine times out of ten, that someone is an old copy of your own server.
What the error means
Only one program can listen on a given address and port at a time. When a second one tries, the OS refuses:
Error: listen EADDRINUSE: address already in use :::3000
Error: listen EADDRINUSE: address already in use 0.0.0.0:8080
OSError: [Errno 98] Address already in use # Python / Linux
OSError: [Errno 48] Address already in use # Python / macOS
bind: address already in use # Go, C, Docker
WSAEADDRINUSE (10048) # Windows
It is the opposite of localhost refused to connect, where nothing is listening at all. DNS never got involved — if the browser said the name itself was unknown, that is ERR_NAME_NOT_RESOLVED instead.
Find what holds the port
| System | Find the process | Stop it safely |
|---|---|---|
| macOS / Linux | lsof -nP -iTCP:3000 -sTCP:LISTEN | kill PID, then kill -9 PID only if it ignores you |
| Linux | ss -ltnp 'sport = :3000' or fuser 3000/tcp | fuser -k 3000/tcp (forceful) |
| Windows cmd | netstat -ano | findstr :3000 (last column = PID) | taskkill /PID 1234 /F |
| Windows PowerShell | Get-NetTCPConnection -LocalPort 3000 | Stop-Process -Id 1234 |
| Docker | docker ps --filter publish=3000 | docker stop NAME |
| systemd | systemctl status myapp / ss -ltnp shows the unit's PID | systemctl stop myapp (not raw kill) |
Read the process name before you stop it. node, python, your app name → leftover. postgres, AirPlay, a system service → pick a different port. On recent macOS, AirPlay Receiver owns ports 5000 and 7000 (Flask's classic clash).
IPv4 vs IPv6 (::: vs 0.0.0.0)
| Bind address | Meaning | Notes |
|---|---|---|
0.0.0.0:3000 | All IPv4 interfaces | Does not accept IPv6 clients |
:::3000 or [::]:3000 | All IPv6 (often dual-stack) | On many Linux builds this also covers IPv4 via v4-mapped addresses |
127.0.0.1:3000 | IPv4 loopback only | Phone / LAN clients cannot reach it |
::1:3000 | IPv6 loopback only | See ECONNREFUSED ::1 |
Node's default server.listen(3000) often shows as :::3000. That can block a second process that tries 0.0.0.0:3000 (or the reverse) depending on net.ipv6.bindv6only. If two tools "shouldn't" collide but do, check both families with ss -ltnp.
SO_REUSEADDR myths
- What it actually does: lets a new socket bind while old connections are still in
TIME_WAIT. Most frameworks (Node, Go'sListen, Python's HTTP servers) already set it. - What it does not do: let two live listeners share the same host:port. If another process is in
LISTEN, you still get EADDRINUSE — raising SO_REUSEADDR will not help. - SO_REUSEPORT (Linux/BSD) is different: multiple sockets can listen together for load-balancing. Node's cluster / some proxies use it. It is not a "just make the error go away" flag.
# Plain Python (frameworks usually do this for you)
import socket
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("0.0.0.0", 8080))
Why it keeps happening
- Old copy in another terminal — or one that survived closing the editor. Ctrl+Z only suspends and keeps the port; use Ctrl+C.
- nodemon / watch mode starting the new copy before the old one released the port. Handle
SIGTERM/SIGINTand callserver.close(). - systemd leftover — you started the app by hand and the unit is still enabled.
systemctl stop …then start only one way. - Multiple Node workers —
cluster.fork()or PM2 instances all told to bind the same port withoutSO_REUSEPORT/ a proper master. Either let the master listen and workers share, or give each worker a unique port behind a proxy. - Docker port maps — two Compose services with
"3000:3000", or a host process plus a published container.docker ps --filter publish=3000shows the container side;ss -ltnpshows the host listener Docker created. - Two apps configured for 3000 (frontend + API) or two Compose services publishing the same host port.
Pick a free port
Most tools take a port option: PORT=3001 npm start, vite --port 5174, flask run --port 5001, python -m http.server 8001. Listening on port 0 asks the OS for any free port (handy in tests). Ports below 1024 need admin rights — that is EACCES, not EADDRINUSE.
Not sure what a mystery PID is? Paste the process name into What is this?.
Related
Reachable locally but not from outside? · Common port numbers (3000, 5000, 8080...) · localhost refused to connect · ECONNREFUSED ::1 · ssh Connection timed out · ERR_NAME_NOT_RESOLVED · JavaScript heap out of memory · EMFILE too many open files
Questions
How do I kill the process on port 3000?
On macOS or Linux: lsof -nP -iTCP:3000 -sTCP:LISTEN (or ss -ltnp), then kill PID. On Windows: netstat -ano | findstr :3000 or Get-NetTCPConnection -LocalPort 3000, then taskkill /PID n /F.
Why is port 5000 already in use on my Mac?
Recent macOS versions use port 5000 (and 7000) for the AirPlay Receiver. Turn it off in System Settings, or run your app on another port such as 5001.
Does SO_REUSEADDR fix EADDRINUSE?
Only for TIME_WAIT leftovers after a process exited. It will not let two live LISTEN sockets share the same host:port. Find and stop the other listener.
What does :::3000 mean in the error?
IPv6 'any' address (often dual-stack). 0.0.0.0 is IPv4-any. On many Linux hosts a :::3000 listener also blocks 0.0.0.0:3000.
I stopped my server but the port is still in use. Why?
Another copy is still running, it was paused with Ctrl+Z, a systemd unit or Docker publish still holds it, or the old socket is in TIME_WAIT.
Is EADDRINUSE the same as EACCES?
No. EADDRINUSE means another process holds the port. EACCES means you lack permission — usually ports below 1024 need admin rights.
Published · updated .