Completely fixing address already in use: Find and kill the process occupying the port (EADDRINUSE)
A red line just appeared in the console — this error means only one thing
If you're trying to start a server and the console dumps bind: address already in use or EADDRINUSE, the message is really saying just one thing.
A single port can be occupied by only one process at a time.
In other words: "someone is already holding the port you want (e.g. 8080)." The culprit is one of three:
- Yourself — a server you started a moment ago is still alive (hot-reload orphan processes are a classic)
- Another process — a completely unrelated app already claimed the same port
- A container — Docker has mapped and is holding the host port
This post is structured so you can finish by following diagnose → terminate → prevent recurrence. Copy-paste from top to bottom.
Step 1: Diagnose — lookup table by error message pattern
First, look at the exact message in the console. The wording differs by environment, but the essence is the same.
| Environment | Actual console output | Likely culprit | First command to run |
|---|---|---|---|
| Node.js | Error: listen EADDRINUSE: address already in use :::8080 | Usually the app itself (duplicate start / nodemon orphan) | lsof -i :8080 |
| Python | OSError: [Errno 98] Address already in use | leftover process from a uvicorn/flask restart | lsof -i :8000 |
| nginx | bind() to 0.0.0.0:80 failed (98: Address already in use) | another web server / previous nginx instance | ss -ltnp 'sport = :80' |
| Docker | Bind for 0.0.0.0:8080 failed: port is already allocated | another container holding the host port | docker ps |
Once you've found your case in the table, use the first command to identify who is holding the port.
Step 2: Terminate — find the occupying process and kill it safely
All examples below use port 8080. Replace it with your own port before running.
Linux / macOS
# 1) (PID) check
lsof -i :8080
# 2) — ss lsof
ss -ltnp 'sport = :8080'
# 3) fuser check
fuser 8080/tcpOnce you've identified the PID column in the lsof -i :8080 output, terminate it.
#
kill -15 <PID>
# 10 quit
kill -9 <PID>
# fuser quit
fuser -k 8080/tcpWindows (PowerShell / CMD)
# PID ( PID)
netstat -ano | findstr :8080
# PID quit
taskkill /PID <PID> /Fkill -15 vs kill -9: order matters
kill -15(SIGTERM): a "clean up and leave" signal. The app closes open files, tears down DB connections, then exits. Always use this first.kill -9(SIGKILL): kills the process immediately. Blindly using -9 can lose in-flight data or leave lock files and temporary sockets behind, making things worse. Use it only as a last resort when SIGTERM does not work.
Step 3: Prevent recurrence — prescriptions by root cause
Killed it, started again, and the same error came back? Then you need to pull the cause out by the roots.
1) Leftover TIME_WAIT sockets → SO_REUSEADDR
If you stop a server and start it again immediately, the socket you just closed stays in TIME_WAIT for tens of seconds and holds the port, causing EADDRINUSE. Enabling SO_REUSEADDR lets you reuse a port in that state.
Node.js — net/http servers have SO_REUSEADDR on by default, but it's still a good idea to handle the error explicitly and fail fast.
const server = http.createServer(app);
server.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error(' 8080 . quit.');
process.exit(1);
}
});
server.listen(8080);Python
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # TIME_WAIT
s.bind(('0.0.0.0', 8000))
s.listen()2) Hot-reload orphan processes
If nodemon or uvicorn --reload exits abnormally, child workers lose their parent and linger as orphan processes still holding the port. They often survive even after you close the terminal, so hunting them down with lsof from Step 2 is the reliable fix.
3) Duplicate starts from systemd or pm2
If a process manager is set to auto-restart, it will collide with a server you started by hand.
# pm2 check
pm2 list
# systemd
systemctl status myapp.serviceBefore a manual test, stop the manager first with pm2 stop <name> or systemctl stop.
4) Docker Compose port mapping conflicts
Bind for 0.0.0.0:8080 failed: port is already allocated means the host port is already taken.
# 8080
docker psIf you find a container whose PORTS column shows 0.0.0.0:8080->..., change only the host port in compose to a free value.
services:
web:
ports:
- "8081:80" # , as-isPractical tip: Locally, the most common causes are "the previous server never died" and "forgot to bring compose down." If you use containers, make
docker compose downa habit at the end of a session. If hot-reload often leaves orphans, registerlsof -i :<port>as a shell alias. Diagnosis drops to 30 seconds.
Conclusion — 3-step summary and copy-paste checklist
- Diagnose: use the exact error text to tell whether the culprit is the app, another process, or a container
- Terminate: find the PID with
lsof -i :<port>(ornetstat -ano), thenkill -15→kill -9if that fails - Prevent recurrence:
SO_REUSEADDR, clean up orphans, and check process-manager / compose ports
# (Linux/macOS)
lsof -i :8080 || ss -ltnp 'sport = :8080'FAQ
Q. Can I just switch to a different port number? A. As a temporary workaround, yes. But changing the port does not make the zombie/orphan process go away — you're still leaking resources. The real fix is to terminate the occupying process.
Q. Rebooting fixed it for me. Is that the right answer? A. A reboot resets every process and TIME_WAIT socket, so of course it clears. But the cause is still there, so it will come back. Use steps 2–3 in this post to remove the root cause.
Q. Bind fails with Permission denied. Is that a port conflict too?
A. No. Ports below 1024 (80, 443, etc.) require root privileges. Run with sudo, use a port 1024 or above like 8080, or grant the capability with setcap. That's a different problem from address already in use.
Sources and checks vary by article. Only articles with a recorded check date, scope and sources below were checked, and only within that scope. For other articles, verify against the current docs for your version before applying anything, and email us about errors. Editorial policy · email us
This article has no recorded human check (date and scope) yet.
Comments
Be the first to comment.