EADDRINUSE has two distinct causes and the fix differs:
- Another process is listening. Find it and stop it, or use a different port.
- No process is listening, and the kernel still holds the address. Sockets from a previous process are in
TIME_WAIT.
One command separates them.
Find the listener
sudo ss -tulpn 'sport = :3000'
Netid State Local Address:Port Peer Process
tcp LISTEN 0.0.0.0:3000 *:* users:(("node",pid=48213,fd=21))
The sudo matters: without it ss will not show the process name for sockets owned by other users, and you get a confusing result that looks like nothing is there.
lsof is the alternative if you prefer it:
sudo lsof -i :3000 -sTCP:LISTEN
On older systems netstat -tulpn | grep :3000 still works; ss is the modern replacement and is significantly faster on a busy host.
Case 1: Something is listening
Identify it properly before you kill anything:
ps -p 48213 -o pid,ppid,user,etime,cmd
PID PPID USER ELAPSED CMD
48213 1 app 02:41:19 node /srv/api/server.js
PPID 1 means it is supervised by systemd or was orphaned. If it is a systemd service, stop the unit rather than the process, or the supervisor restarts it immediately and the port is taken again before you can bind:
systemctl status 48213 # tells you which unit owns the PID
sudo systemctl stop myapi
For something genuinely stray:
kill 48213 # SIGTERM, lets it clean up
kill -9 48213 # only if it ignores SIGTERM
kill -9 gives the process no chance to close its listening socket or flush anything, which is how you end up with the TIME_WAIT situation below.
Avoid fuser -k 3000/tcp and kill $(lsof -t -i:3000) as reflexes. Both kill whatever is there without you having read what it is, which in a shared environment is how the wrong thing gets killed.
Case 2: Nothing is listening
sudo ss -tulpn 'sport = :3000' # no output
ss -tan 'sport = :3000' | head
State Local Address:Port Peer Address:Port
TIME-WAIT 10.0.1.5:3000 10.0.1.9:54122
TIME-WAIT 10.0.1.5:3000 10.0.1.9:54123
The old process is gone and its connections are still winding down. TCP keeps the pair in TIME_WAIT for twice the maximum segment lifetime, 60 seconds on Linux, so that late packets from the old connection are not delivered to a new one.
Wait a minute and it clears. Or, better, make your server able to bind anyway.
SO_REUSEADDR is the real fix
A server should set SO_REUSEADDR before binding. It permits binding to a local address that has connections in TIME_WAIT, which is exactly the "I just restarted my service" case.
Most frameworks do this for you. Some do not:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("0.0.0.0", 3000))
// Go sets SO_REUSEADDR on listening sockets by default.
ln, err := net.Listen("tcp", ":3000")
This does not let two processes listen on the same port. It only allows binding over lingering TIME_WAIT entries. SO_REUSEPORT is the different option that genuinely allows multiple listeners, used deliberately for load balancing across worker processes.
Do not reach for net.ipv4.tcp_tw_reuse. It is a client-side setting for outgoing connections, it does not help a listener, and tcp_tw_recycle, which people often mean, was removed from the kernel in 4.12 because it broke connections from behind NAT.
The IPv4 and IPv6 overlap
Error: listen EADDRINUSE: address already in use :::3000
The :::3000 is IPv6 [::]:3000. By default a socket bound to [::] also accepts IPv4 connections through the dual-stack mapping, so an IPv6 wildcard bind occupies the IPv4 port too. A second process binding 0.0.0.0:3000 then collides with something that does not appear when you only look at IPv4.
sudo ss -tulpn | grep :3000 # shows both families
Check both before concluding nothing is there.
Ports below 1024
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
If binding to 80 or 443 fails with permission denied rather than address in use, that is a different problem: privileged ports need CAP_NET_BIND_SERVICE. For a systemd service:
[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE
Worth knowing because the two errors get conflated, and running the whole service as root to work around it is a poor trade.
In containers
Inside a container the port is namespaced, so a conflict is usually on the host side of a published port:
docker run -p 3000:3000 myapp # 3000 on the host must be free
Let Docker choose a host port when you do not care:
docker run -p 3000 myapp
docker port <container>
Two containers can both listen on 3000 internally without any conflict, as long as they publish to different host ports or none at all.
In a Kubernetes Pod, containers share a network namespace, so two containers in the same Pod listening on the same port do conflict. hostPort and hostNetwork reintroduce host-level conflicts and are worth avoiding for that reason among others.
A checklist
sudo ss -tulpn 'sport = :PORT'. The sudo is required to see process names.- Something listening →
ps -p PID -o pid,ppid,user,etime,cmdand read it. PPID 1→ find the unit withsystemctl status PIDand stop that, not the PID.- Nothing listening →
ss -tan 'sport = :PORT'and look forTIME-WAIT. TIME_WAIT→ wait ~60s, or setSO_REUSEADDRin the server.:::3000in the message → an IPv6 wildcard bind is holding IPv4 too.- Port under 1024 failing on permissions →
CAP_NET_BIND_SERVICE, not root. - Docker → the conflict is the host side of
-p; omit the host port to auto-assign.
Frequently Asked Questions
How do I find which process is using a port on Linux?
sudo ss -tulpn 'sport = :3000', and the sudo is not optional: without it ss omits the process name for sockets owned by other users, so the output looks unhelpfully empty. sudo lsof -i :3000 -sTCP:LISTEN gives the same answer. On older systems netstat -tulpn | grep :3000 still works, though ss is the modern replacement and is much faster on a host with many connections. Follow up with ps -p <pid> -o pid,ppid,user,etime,cmd before you act on it.
Why is the port in use when nothing is listening?
Connections from the previous process are in TIME_WAIT. TCP holds the address and port pair for twice the maximum segment lifetime, 60 seconds on Linux, so that delayed packets from the old connection cannot be delivered to a new one that happens to reuse the same pair. ss -tan 'sport = :3000' shows the entries. It clears on its own, and the proper fix is for the server to set SO_REUSEADDR before binding, which is exactly what that option is for.
Does SO_REUSEADDR let two processes share a port?
No. It allows a bind to succeed when the address has connections lingering in TIME_WAIT, which is the restart case. Two processes cannot both hold a listening socket on the same address and port with it. The option that genuinely permits that is SO_REUSEPORT, which is a deliberate feature for spreading accepted connections across several worker processes, and it requires every listener to set it. Confusing the two leads people to expect a behaviour SO_REUSEADDR was never meant to provide.
Should I use tcp_tw_reuse to get rid of TIME_WAIT?
No. net.ipv4.tcp_tw_reuse applies to outgoing client connections and does nothing for a listening socket, so it will not fix this error. The setting people usually mean is tcp_tw_recycle, which was removed from the Linux kernel in 4.12 because it broke connections from clients behind NAT in ways that were very hard to diagnose. TIME_WAIT exists for a reason; SO_REUSEADDR on the server is the supported way to restart without waiting for it.
What does ":::3000" mean in the error message?
It is the IPv6 wildcard address [::] with port 3000. A socket bound there accepts IPv4 connections as well through dual-stack mapping, unless IPV6_V6ONLY is set, so an IPv6 wildcard bind occupies the IPv4 port too. A process then trying to bind 0.0.0.0:3000 collides with something that does not appear if you only inspect IPv4. Always look at both families, which sudo ss -tulpn | grep :3000 does by default.