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.