Python — OSError: [Errno 98] Address already in use when binding a socket
Resolve address-in-use errors by releasing the socket, enabling reuse options and understanding TIME_WAIT behavior.
Symptoms
- OSError: [Errno 98] Address already in use when binding
- The server worked earlier and now cannot restart
- Restarting fast after a stop fails, but waiting helps
- Two workers try to bind the same port
Possible causes
- Another live process is bound to the same port
- A recently closed socket is in TIME_WAIT holding the port
- The app is started twice, for example by a reloader and a manual run
- A worker configuration binds the same port in every worker
Diagnosis steps
Identify what holds the port
ss -ltnp | grep :8000Interpretation
The output shows the process and PID listening on the port, distinguishing a live process from a lingering socket.
Check for TIME_WAIT sockets
ss -tan | grep :8000Interpretation
Sockets in TIME_WAIT briefly hold the local port after a close, which explains immediate restart failures.
Confirm reuse options in the code
grep -n "SO_REUSEADDR\|allow_reuse_address" app/Interpretation
Setting SO_REUSEADDR or the framework equivalent lets a bind succeed while old connections are draining.
Root cause
The local address is still in use by a live process or a socket in TIME_WAIT, so the bind call cannot claim it. The code is typically correct; the port state is the problem.
Fix
Stop the process holding the port, or enable SO_REUSEADDR and run a single binder per port. Avoid launching duplicate instances and give TIME_WAIT sockets a moment to clear when necessary.
Verify the fix
Bind again and confirm the server starts, and confirm only one process listens on the port.
Symptom walkthrough
A server fails to start with OSError: [Errno 98] Address already in use when binding its socket. It may have restarted many times before, and a quick restart right after a stop fails while waiting a few seconds makes it work. This is the signature of a live process or a socket in TIME_WAIT still owning the local port.
Fix in practice
Find and stop the process bound to the port, enable SO_REUSEADDR or the framework equivalent so binding can succeed while old connections drain, and ensure only one process binds each port. When duplicate instances are the cause, fix the startup logic rather than the socket options.
Verification
Start the server again and confirm it binds successfully, then list listeners to confirm exactly one process owns the port. A clean single listener with a successful start confirms the fix.
Diagnostic commands
Check the behavior with commands like these:
ss -ltnp | grep :8000
ss -tan | grep :8000
grep -n "SO_REUSEADDR\|allow_reuse_address" app/