Ordered by how often each one turns out to be the answer.
An earlier copy of the same program is still running
CommonA dev server left running in another terminal, a process that did not exit when its terminal closed, or a service manager that already started it.
Confirm
lsof -nP -iTCP:PORT -sTCP:LISTEN
The program and process ID holding the port (on Linux, sudo ss -ltnp 'sport = :PORT' shows the same)
Fix
- Stop the old copy the way it was started: Ctrl+C in its terminal, or systemctl stop for a service.
- If it is truly stray, end it by process ID with kill PID, and only use kill -9 if it does not exit.
A different service uses that port
CommonPorts such as 80, 3000, 5000, 5432 and 8080 are popular defaults: a system web server, a database or another project may already use it.
Confirm
sudo ss -ltnp 'sport = :PORT'
A program you did not expect on the port
Fix
- Run your program on another port, usually through its configuration or a PORT environment variable.
- Or stop or reconfigure the other service if you no longer need it on that port.
Listening on 0.0.0.0 while something holds the port on one address
Occasional0.0.0.0 covers every address on the machine, so it conflicts with a program on 127.0.0.1 or a specific address with the same port.
Confirm
sudo ss -ltnp 'sport = :PORT'
A listener on 127.0.0.1:PORT or another single address
Fix
- Pick a different port, or bind your program to a specific address that is free, for example 127.0.0.1 if only local clients need it.
A quick restart while old connections are in TIME_WAIT
OccasionalThe program itself exited, but its recent connections linger briefly. A server that does not set SO_REUSEADDR cannot listen again until they expire.
Confirm
ss -tan state time-wait 'sport = :PORT'
Connections in TIME_WAIT on the port, and no process listening on it
Fix
- Set SO_REUSEADDR on the listening socket before bind, in your own socket code. Most server frameworks already do.
- Otherwise wait a short while and start it again.
A container publishes the port
OccasionalA running container with that port published holds it on the host, even if you forgot it was there.
Confirm
docker ps --format '{{.Names}} {{.Ports}}'A container whose ports include the host port, such as 127.0.0.1:3029->3000/tcp; ss names the holder as docker-proxy
Fix
- Stop that container, or publish a different host port. The Docker side of this error has its own page.