OSError: [Errno 98] Address already in use in Python
This error occurs when binding to a port that is already in use. Terminate the blocking process with lsof -i :
Root Cause Analysis
This error occurs when Python tries to bind a network socket or web server (such as FastAPI, Flask, or Uvicorn) to a specific TCP port and network interface, but that port is already bound and occupied by another active process.
Cause 1: Orphaned Zombie Server Processes
Stopping a development server with Ctrl+Z (suspending) instead of Ctrl+C (terminating) leaves the server running in the background. Relaunching the script fails because port 8000 remains occupied.
Cause 2: Sockets in TIME_WAIT State
When a server closes without the SO_REUSEADDR socket option, the operating system kernel keeps the TCP socket in TIME_WAIT for 1-2 minutes to ensure lingering packets dissipate.
Cause 3: Port Collisions Between Simultaneous Services
Attempting to launch two microservices (e.g. Django and FastAPI) on the same default port (e.g. 8000 or 5000) causes the second process to raise OSError: [Errno 98] Address already in use (or [Errno 10048] Only one usage of each socket address on Windows).
Reproduction Code (MCVE)
import socket
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind(('127.0.0.1', 54321))
s1.listen(1)
# Binding a second socket to the same address and port raises OSError
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.bind(('127.0.0.1', 54321))
Solution 1: Enable the SO_REUSEADDR Socket Option
Configure socket.SO_REUSEADDR before binding so the operating system permits immediate port reuse after server restarts.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Enable port reuse flag
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 0)) # Port 0 assigns an available port
port = s.getsockname()[1]
print(f'Socket bound successfully on port: {port}')
s.close()
Solution 2: Inspect and Terminate the Conflicting Process via CLI
Identify the process occupying the target port using OS diagnostic utilities and terminate it gracefully.
import sys
# Diagnostic commands for developers:
# Linux/macOS: lsof -i :8000 -> kill -9 <PID>
# Windows: netstat -ano | findstr :8000 -> taskkill /PID <PID> /F
print('Port diagnostic verified.')
Common Mistakes & Edge Cases
1. Windows Errno 10048 vs Linux Errno 98
- Linux / macOS:
OSError: [Errno 98] Address already in use - Windows:
OSError: [WinError 10048] Only one usage of each socket address is normally permitted
2. Dynamic Port Binding with Port 0
In unit test suites that spin up temporary web servers, pass port=0 to let the operating system assign an available ephemeral port, eliminating test concurrency collisions.
3. Contrasting OSError vs ConnectionRefusedError
OSError [Errno 98] occurs on the server side when binding to a busy port. ConnectionRefusedError occurs on the client side when trying to connect to a port where no server is listening.
4. Note de Reproductibilité Environnementale
Le comportement des commandes système et des résolutions de paquets dépend fortement de votre système d'exploitation (Windows, macOS, Linux), de l'architecture processeur (x86_64 vs ARM64) et de la configuration des permissions locales. Adaptez les chemins et les permissions selon votre environnement d'exécution spécifique.