Address already in use — port binding conflict
bind: Address already in use error on application startup
Focused incident mode — strips away everything but this runbook.
Symptoms
- bind: Address already in use error on application startup
- Service fails to start after a crash without cleanup
- Multiple services compete for the same port
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Listening ports
ss -ltnp | grep :<PORT>Process using the port
ss -ltnp sport = :<PORT>
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- ss shows the old PID (now dead or zombie) still holding the port
- Application was force-killed (SIGKILL) without port cleanup
Confirm before fixing
ss -ltnp sport = :<PORT>Confirm the stale process is the old instance
Fix
kill -9 <stale-PID>Force-kill the stale process to release the port
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
ss -ltnp | grep :<PORT>Find who holds the port
ps -p <PID> -o pid,ppid,cmdIdentify the process
kill -TERM <PID>Stop the process gracefully
sleep 2 && ss -ltnp | grep :<PORT>Verify the port is free
Prevention
- Set SO_REUSEADDR in applications that need to restart quickly.
- Use systemd socket activation to have systemd manage port binding.
- Monitor port conflicts with a cron check on ss output.
- Configure services with unique default ports to avoid collisions.
Related runbooks
Same stack, same failure family — worth a skim.
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.