How to Resolve Python "OSError: [Errno 98] Address already in use"
When developing network applications (like web servers, socket servers, or APIs) in Python, you might encounter the OSError: [Errno 98] Address already in use
or the closely related socket.error: [Errno 98] Address already in use
. This error signals that the network address (specifically, the combination of IP address and port number) your application is trying to bind to is currently unavailable on your system.
This guide explains the common causes of this error and provides practical solutions for resolving it in various scenarios.
Understanding the Error: Occupied Network Address
Network applications "listen" for incoming connections on a specific network interface (IP address) and port number. Binding is the process of reserving this address/port combination for exclusive use by your application. The "Address already in use" error means this reservation failed because:
- Another application process is currently actively bound to and using that exact IP address and port.
- A socket from a previous run of your application (or another application) that used the same address/port recently closed but is still lingering in the operating system's
TIME_WAIT
state, preventing immediate reuse.
Cause 1: Another Process is Using the Port
The most straightforward cause is that another program (maybe a previous instance of your own app that didn't shut down cleanly, a different web server, or another network service) is actively running and bound to the port you're trying to use.
Solution 1: Find and Stop the Conflicting Process
You need to identify the process occupying the port and terminate it if it's not supposed to be running or if it's a zombie process.
Finding the Process ID (PID) on Linux/macOS (lsof
)
Open your terminal and use the lsof
(list open files) command. Replace 8000
with the port number causing the error.
# Check which process uses TCP port 8000
lsof -i :8000
# Or if you get permission errors:
sudo lsof -i :8000
# Example Output:
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# python3 12345 myuser 3u IPv4 0xabcdef0123456789 0t0 TCP *:8000 (LISTEN)
Look for the PID
(Process ID) column in the output (e.g., 12345
in the example).
Finding the Process ID (PID) on Windows (netstat
)
Open Command Prompt (cmd) or PowerShell and use netstat
. Replace 8000
with your port number.
netstat -ano | findstr ":8000"
:: Example Output:
:: TCP 0.0.0.0:8000 0.0.0.0:0 LISTENING 9876
Look at the last column for the PID (e.g., 9876
in the example).
Stopping the Process (kill
/Task Manager)
- Linux/macOS: Use the
kill
command with the PID you found. The-9
flag forcefully terminates the process.kill -9 <PID>
# Example: kill -9 12345
# Use sudo if necessary: sudo kill -9 12345 - Windows:
- Open Task Manager (
Ctrl+Shift+Esc
). - Go to the Details tab (or Processes tab in older Windows versions).
- Find the process with the matching PID.
- Right-click the process and select "End task" or "End process".
- Alternatively, use
taskkill
in Command Prompt (run as Administrator):taskkill /PID <PID> /F
:: Example: taskkill /PID 9876 /F
- Open Task Manager (
After stopping the conflicting process, try running your Python application again.
Cause 2: Socket Stuck in TIME_WAIT
State
When a TCP socket connection closes, the endpoint that initiated the close often enters a TIME_WAIT
state for a short period (e.g., 30-120 seconds). This is part of the TCP protocol to ensure any lingering packets are handled correctly. During TIME_WAIT
, the operating system typically prevents another socket from binding to the exact same address/port combination. If you stop and immediately restart your server, you might hit this state.
Solution 2: Allow Address Reuse (SO_REUSEADDR
)
You can instruct the operating system to allow your new socket to bind even if an old socket on the same address/port is in TIME_WAIT
. This is done via the SO_REUSEADDR
socket option.
Important: This option must be set before calling bind()
.
Using socket.setsockopt()
(Raw Sockets)
If you are working directly with Python's socket
module:
import socket
HOST = socket.gethostname() # Or 'localhost', '0.0.0.0', etc.
PORT = 8000
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# ✅ Set SO_REUSEADDR option BEFORE binding
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
print(f"Binding to {HOST}:{PORT}...")
sock.bind((HOST, PORT))
sock.listen(1)
print("Server is listening...")
# ... rest of your server logic (accept connections, etc.) ...
except OSError as e:
print(f"Binding failed: {e}")
finally:
print("Closing socket.")
sock.close()
Setting the third argument of setsockopt
to 1
enables the SO_REUSEADDR
option.
Using allow_reuse_address
(socketserver
/http.server
)
If using higher-level modules like socketserver
or http.server
, they often provide a simpler attribute to control this:
import socketserver
import http.server
PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler # Example handler
# Use a context manager for clean shutdown
with socketserver.TCPServer(("", PORT), Handler) as httpd:
# ✅ Set allow_reuse_address to True BEFORE serving
httpd.allow_reuse_address = True
print(f"Serving HTTP on port {PORT} (allowing address reuse)...")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("\nServer stopped.")
Setting allow_reuse_address = True
effectively sets the SO_REUSEADDR
option on the underlying socket for you.
Flask Development Server (use_reloader=False
)
When running Flask in debug mode (debug=True
), it often uses a reloader process that automatically restarts the server when code changes. This rapid restarting can frequently trigger the TIME_WAIT
issue. While SO_REUSEADDR
helps, disabling the reloader during specific debugging phases can also prevent the error.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
# ✅ Setting use_reloader=False prevents auto-restarts causing TIME_WAIT issues
# Note: You lose the auto-reload feature when code changes.
app.run(host='0.0.0.0', port=5000, debug=True, use_reloader=False)
# For production, use a proper WSGI server (Gunicorn, uWSGI) which handle
# socket binding more robustly, usually using SO_REUSEADDR by default.
# Setting debug=False also typically disables the reloader.
# app.run(debug=False)
Solution 3: Use a Different Port or Host (Workaround)
As a temporary fix or for testing, you can simply change the PORT
number your application tries to bind to (e.g., 8001
instead of 8000
) or potentially the HOST
IP address if applicable. This avoids the conflict but doesn't address the root cause if the original port should have been available.
HOST = 'localhost'
PORT = 8001 # Changed from 8000
# ... rest of socket/server setup ...
# sock.bind((HOST, PORT))
# ...
Conclusion
The OSError: [Errno 98] Address already in use
means the network address/port your Python application wants to use is unavailable.
- Check for existing processes: Use tools like
lsof
(Linux/macOS) ornetstat
(Windows) to find and, if necessary, terminate any other process using the port. - Handle
TIME_WAIT
: For servers you frequently restart during development, set theSO_REUSEADDR
socket option before binding. Usesocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
for raw sockets or theallow_reuse_address = True
attribute for libraries likesocketserver
. For Flask development, consideruse_reloader=False
. - Workaround: Temporarily use a different port number if the specific port isn't critical.
Applying the SO_REUSEADDR
option in your server code is often the most effective long-term solution for issues caused by rapid restarts during development.