OSError: [Errno 98] Address already in use
Python · updated 2026-11-03
Raised when a server binds a host and port that something already holds: socket.bind(), uvicorn, gunicorn, Flask and Django runserver all hit it at startup. On macOS the number is [Errno 48].
Traceback (most recent call last):
File "/app/server.py", line 40, in <module>
app.run(host="0.0.0.0", port=5000)
...
File "/usr/lib/python3.12/socketserver.py", line 473, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in useQuick fix
Find what holds the port with lsof -nP -iTCP:<port> -sTCP:LISTEN (or ss -ltnp on Linux), stop it if it is an old copy of your app, or start on a different port. On macOS, port 5000 is often taken by AirPlay Receiver.
- Run lsof -nP -iTCP:5000 -sTCP:LISTEN (replace 5000 with your port) to see the PID.
- Check it with ps -p <PID> -o command, then stop it with kill <PID>.
- Read the port from an environment variable so you can change it without code edits.
- For your own socket servers, set SO_REUSEADDR before bind so restarts do not wait for TIME_WAIT.
- On macOS, turn off AirPlay Receiver if port 5000 or 7000 is busy.
import os, socket
port = int(os.environ.get("PORT", "8000"))
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # restart without waiting
sock.bind(("0.0.0.0", port))
sock.listen()Why it happens
An old copy of the server is still running
A previous run left in the background, a crashed debugger session, or a dev server reloader that spawned a child keeps the port.
Another service uses the same port
Two apps configured for 8000, a Docker container publishing the port, or macOS AirPlay Receiver on 5000 and 7000.
Restarting a socket server too quickly
Without SO_REUSEADDR, a port can stay unavailable for a short time after the previous process exits (TIME_WAIT).
Two workers binding the same port
Starting the app twice in one deploy, or a process manager and a manual run both binding the port, makes the second one fail.
Other fixes
- With gunicorn, let it own the socket and run multiple workers instead of starting several processes yourself.
- In tests, bind to port 0 and read the assigned port so test runs never collide.
Same error, other wording
- OSError: [Errno 48] Address already in use
- ERROR: [Errno 98] error while attempting to bind on address ('0.0.0.0', 8000): address already in use
- [ERROR] Connection in use: ('0.0.0.0', 8000)
Let your coding agent catch the next one
Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:
> Find the 'Address already in use' errors in production, show me which port and which process held it, and fix the restart or deploy step so only one copy binds the port.
Related errors
- Error: listen EADDRINUSE: address already in use :::3000
- django.db.utils.OperationalError: no such table: orders_order
- ModuleNotFoundError: No module named 'x'
References: Python docs: socket (SO_REUSEADDR, bind), Uvicorn docs: settings (host, port, fd)