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)와 이름 확인
lsof -i :8080
# 2) 대체 명령 — ss는 lsof보다 가볍고 리눅스 기본 탑재
ss -ltnp 'sport = :8080'
# 3) fuser로 한 번에 확인
fuser 8080/tcpOnce you've identified the PID column in the lsof -i :8080 output, terminate it.
# 먼저 우아하게 (권장)
kill -15 <PID>
# 10초 기다려도 안 죽으면 강제 종료
kill -9 <PID>
# fuser로 한 방에 종료하고 싶다면
fuser -k 8080/tcpWindows (PowerShell / CMD)
# 포트를 점유한 PID 찾기 (맨 끝 숫자가 PID)
netstat -ano | findstr :8080
# 해당 PID 강제 종료
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 사용 중. 점유 프로세스를 먼저 종료하세요.');
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가 같은 앱을 이미 띄워두지 않았는지 확인
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" # 왼쪽(호스트)만 변경, 오른쪽(컨테이너)은 그대로Practical 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.
Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.
Comments
Be the first to comment.