OSError: [Errno 98] Address already in use in Python (tested)
OSError: [Errno 98] Address already in use means bind() found the port taken: either another process is listening on it, or your previous server left it in TIME_WAIT. We tested both on Linux: SO_REUSEADDR fixed the restart case only when the old and the new socket both set it.
1. The error
import socket
a = socket.create_server(("127.0.0.1", 8964))
b = socket.create_server(("127.0.0.1", 8964))
Output:
Traceback (most recent call last):
File "/tmp/ad/b1.py", line 4, in <module>
b = socket.create_server(("127.0.0.1", 8964))
File "/usr/lib/python3.13/socket.py", line 949, in create_server
raise error(err.errno, msg) from None
OSError: [Errno 98] Address already in use (while attempting to bind on address ('127.0.0.1', 8964))
Something already listens on that address and port: another copy of your script, a server you started earlier that is still running in another terminal or in the background, or a different program. Find it with ss -ltnp | grep :8964 (Linux) or lsof -i :8964 (macOS/Linux), then stop it or choose another port.
2. It is a plain OSError with errno EADDRINUSE
import errno, socket
a = socket.create_server(("127.0.0.1", 8964))
try:
socket.create_server(("127.0.0.1", 8964))
except OSError as e:
print(type(e).__name__, e.errno, errno.errorcode[e.errno])
print("ConnectionError?", isinstance(e, ConnectionError), "| PermissionError?", isinstance(e, PermissionError))
Output:
OSError 98 EADDRINUSE
ConnectionError? False | PermissionError? False
There is no dedicated subclass, so catch OSError and compare e.errno == errno.EADDRINUSE (98 on Linux; the number differs on macOS and Windows, the constant does not).
3. Address already in use right after restarting your server
import socket
def bind(port, reuse):
s = socket.socket()
if reuse:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(("127.0.0.1", port)); s.listen()
return s
def restart(port, old_reuse):
# a server that accepted a connection and closed first leaves TIME_WAIT behind
srv = bind(port, old_reuse)
c = socket.create_connection(("127.0.0.1", port)); conn, _ = srv.accept()
conn.close(); srv.close(); c.close()
for reuse in (False, True):
try:
bind(port, reuse).close()
print(f" restart with SO_REUSEADDR={reuse}: bound")
except OSError as e:
print(f" restart with SO_REUSEADDR={reuse}: {e}")
print("old server WITHOUT SO_REUSEADDR:"); restart(8965, old_reuse=False)
print("old server WITH SO_REUSEADDR:"); restart(8966, old_reuse=True)
Output:
old server WITHOUT SO_REUSEADDR:
restart with SO_REUSEADDR=False: [Errno 98] Address already in use
restart with SO_REUSEADDR=True: [Errno 98] Address already in use
old server WITH SO_REUSEADDR:
restart with SO_REUSEADDR=False: [Errno 98] Address already in use
restart with SO_REUSEADDR=True: bound
When a server closes a connection first, the port stays in TIME_WAIT for up to a minute or so (ss -tan shows it), and a plain bind() fails during that time. SO_REUSEADDR fixes it, but on Linux only if both the old and the new socket set it: setting it only in the restarted server still failed. Set it before bind() in every run, and the next restart binds immediately. It does not let two live servers share a port.
4. What the standard library already does
import socket
print("create_server sets SO_REUSEADDR:",
socket.create_server(("127.0.0.1", 8967)).getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) != 0)
s = socket.create_server(("127.0.0.1", 0)) # port 0: the OS picks a free port
print("free port:", s.getsockname()[1] > 0)
Output:
create_server sets SO_REUSEADDR: True
free port: True
import http.server, socketserver
print("HTTPServer.allow_reuse_address:", http.server.HTTPServer.allow_reuse_address)
print("TCPServer.allow_reuse_address:", socketserver.TCPServer.allow_reuse_address)
Output:
HTTPServer.allow_reuse_address: 1
TCPServer.allow_reuse_address: False
socket.create_server() sets SO_REUSEADDR on POSIX for you, and http.server.HTTPServer sets allow_reuse_address, but a plain socketserver.TCPServer does not: subclass it with allow_reuse_address = True. Binding to port 0 lets the OS pick a free port, which is the simplest fix for tests.
Related: EADDRINUSE: address already in use (Node and others) · [Errno 111] Connection refused · socket errors and errno codes.
Frequently asked questions
How do I fix Errno 98 Address already in use in Python?
Find the process holding the port (ss -ltnp or lsof -i :PORT) and stop it, or use another port. For quick restarts, set SO_REUSEADDR before bind() in every run.
Why does SO_REUSEADDR not fix Address already in use?
On Linux the TIME_WAIT socket left by the old server must also have had SO_REUSEADDR set. It also never allows two servers listening on the same port.
Does http.server set SO_REUSEADDR?
http.server.HTTPServer and socket.create_server do; plain socketserver.TCPServer does not (allow_reuse_address = False).
Written with AI assistance. Measured on 2026-10-23 with Python 3.13.5 on Linux (Debian 13). Each block was run verbatim and the output pasted unedited. PlainHeaders is our extension; Python is free.