Technology · PRACTICAL GUIDE
Linux says “Address already in use”? Prove the socket owner before killing or retrying
A port number alone is not the incident. Capture the protocol, family, address, port or path and network namespace; prove which process or socket unit owns that exact tuple; then repair one ownership boundary and repeat the start.

A port number alone is not the incident. Capture the protocol, family, address, port or path and network namespace; prove which process or socket unit owns that exact tuple; then repair one ownership boundary and repeat the start.
EADDRINUSE reports a bind conflict for the requested address, not permission or a nonexistent local address. TCP and UDP are separate; IPv4 and IPv6 wildcard listeners can still overlap depending on configuration.
1. Freeze the exact bind tuple and failing syscall
Record the exact error and bind arguments: TCP, UDP or UNIX socket; IPv4 or IPv6; specific or wildcard address; port or pathname; and the process, container, service unit and network namespace. Distinguish EADDRINUSE from EADDRNOTAVAIL and EACCES before changing anything.
Preserve the launch command, configuration, unit files and timestamps. Do not kill every process matching a runtime name, delete a UNIX-socket pathname or enable a reuse flag until the requested tuple and owning boundary are known.
2. Inspect the owner in the correct namespace
Run socket inspection inside the namespace that attempted the bind. Use numeric listening and bound-inactive views, then record local tuple, state, UID, socket inode, PID and command where permissions allow. Compare that evidence with the service and container start timeline.
Check socket units as well as service processes. With socket activation, systemd can legitimately hold the listener and pass it to the daemon. A service that ignores the inherited descriptor and binds again creates an ownership conflict even though its companion process appears expected.
3. Classify wildcard, activation and handoff collisions
Classify whether a specific address collides with a wildcard listener, whether an IPv6 wildcard also covers IPv4, whether TCP or UDP is involved, and whether a UNIX pathname or abstract socket is the endpoint. Avoid treating every occurrence of the same number as the same socket.
If a tool first asks the kernel for a free port, closes that temporary socket and binds later, another process can win between check and use. That handoff race needs an atomic reservation or bounded retry at the real bind, not repeated preflight scans.
4. Repair one proven ownership boundary
When the owner is unintended, stop it through its real supervisor and verify the socket closes before restarting. When the owner is the intended socket unit, make the service consume the inherited descriptor. When two configured listeners overlap, choose one authoritative address and family.
Use SO_REUSEADDR only for the documented restart behavior it permits. Use SO_REUSEPORT only when every listener intentionally participates before bind and the same-UID security boundary is acceptable. Do not use either option to conceal an unexplained owner.
5. Repeat the start and prove stable ownership
In staging or a controlled maintenance window, start the service from a clean state and prove the exact tuple belongs to the expected PID or unit in the expected namespace. Verify the health endpoint or protocol response, then stop and restart through the real supervisor.
Repeat rapid restart and one concurrent-launch test. Acceptance requires one documented owner or one designed reuse group, no intermittent bind failures, no orphan listener after stop, and a rollback path. If a race recurs, keep the timeline and repair the handoff rather than increasing blind retries.
