n8n-io/n8n · error · OSError
Port {config.port} is already in use
Error message
Port {config.port} is already in use What it means
Thrown by HealthCheckServer.start when asyncio.start_server fails with EADDRINUSE, meaning the configured health check port is already bound by another process. The original OSError is chained (from e) so the traceback is preserved, but the message is made more user-friendly by naming the specific port.
Source
Thrown at packages/@n8n/task-runner-python/src/health_check_server.py:29
class HealthCheckServer:
def __init__(self):
self.server: asyncio.Server | None = None
self.logger = logging.getLogger(__name__)
async def start(self, config: HealthCheckConfig) -> None:
try:
self.server = await asyncio.start_server(
self._handle_request, config.host, config.port
)
# for OS-assigned port in tests
actual_port = self.server.sockets[0].getsockname()[1]
self.logger.info(
f"Health check server listening on {config.host}, port {actual_port}"
)
except OSError as e:
if e.errno == errno.EADDRINUSE:
raise OSError(f"Port {config.port} is already in use") from e
else:
raise
async def stop(self) -> None:
if self.server:
self.server.close()
await self.server.wait_closed()
self.server = None
self.logger.info("Health check server stopped")
async def _handle_request(
self, _reader: asyncio.StreamReader, writer: asyncio.StreamWriter
) -> None:
try:
writer.write(HEALTH_CHECK_RESPONSE)
await writer.drain()
except Exception:
passView on GitHub (pinned to 5ac6606e81)
Solutions
- Find and stop the process holding the port: use 'lsof -i :<port>' or 'ss -tlnp | grep <port>'.
- Change N8N_RUNNERS_HEALTH_CHECK_SERVER_PORT to a different available port.
- Set the port to 0 to let the OS assign an available port automatically (useful in tests).
- Ensure previous runner processes are fully terminated before starting new ones.
Example fix
# before export N8N_RUNNERS_HEALTH_CHECK_SERVER_PORT=8080 # another process is on 8080 # after — use a different port export N8N_RUNNERS_HEALTH_CHECK_SERVER_PORT=8081 # or find and kill the stale process # lsof -i :8080 # then kill <PID>
Defensive patterns
Strategy: try-catch
Validate before calling
import socket
def is_port_available(host: str, port: int) -> bool:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
try:
s.bind((host, port))
return True
except OSError:
return False
if not is_port_available(config.host, config.port):
raise RuntimeError(f'Port {config.port} is already in use') Try / catch
from health_check_server import HealthCheckServer
try:
await server.start(config)
except OSError as e:
if 'already in use' in str(e):
print(f'Port {config.port} is busy — try a different port or stop the conflicting process')
config.port = 0 # let OS assign
await server.start(config) Prevention
- Use port 0 for OS-assigned ports in development and testing.
- Document the health check port and ensure it doesn't conflict with other services.
- Ensure previous runner processes are terminated before starting new ones.
- Use liveness probes that don't conflict with the health check server.
When it happens
Trigger: The Python task runner attempts to bind its health check TCP server to config.port, but another process (another runner instance, a different service, or a stale runner process) is already listening on that port. asyncio.start_server raises OSError with errno EADDRINUSE.
Common situations: Running multiple runner instances on the same host with the same health check port. A previous runner process didn't shut down cleanly and is still holding the port. Another application happens to use the same port. Port conflict in a container orchestration environment where multiple pods share host networking.
Related errors
- Port must be between 0 and 65535, got {port}
- Environment variable N8N_RUNNERS_GRANT_TOKEN is required
- Task timeout must be positive, got {task_timeout}
- Auto shutdown timeout must be non-negative, got {auto_shutdo
- Graceful shutdown timeout must be positive, got {graceful_sh
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/6c65ac71ed32302f.
Report an issue: GitHub.