oraios/serena · error · RuntimeError
No free ports found starting from {start_port}
Error message
No free ports found starting from {start_port} What it means
The dashboard's port-finding helper scans ports starting at start_port trying to bind; if it exhausts the range without finding a bindable port it raises RuntimeError('No free ports found starting from {start_port}'). Serena throws this to prevent starting the web dashboard on an occupied or restricted port.
Source
Thrown at src/serena/dashboard.py:808
try:
language = LanguageServerId(request_remove_language.language)
except ValueError:
raise ValueError(f"Invalid language server identifier: {request_remove_language.language}")
# remove_language is already thread-safe
self._agent.remove_language_server(language)
@staticmethod
def _find_first_free_port(start_port: int, host: str) -> int:
port = start_port
while port <= 65535:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind((host, port))
return port
except OSError:
port += 1
raise RuntimeError(f"No free ports found starting from {start_port}")
def run(self, port: int) -> int:
"""
Runs the dashboard on the given host and port and returns the port number.
"""
# patch flask.cli.show_server to avoid printing the server info
from flask import cli
# ty cannot model reassigning a third-party module's function attribute (it rejects any
# replacement, even one with an identical signature), so the monkeypatch is suppressed here
cli.show_server_banner = lambda *args, **kwargs: None # ty: ignore[invalid-assignment]
self._app.run(host=self._host, port=port, debug=False, use_reloader=False, threaded=True)
return port
def run_in_thread(self) -> tuple[threading.Thread, int]:
port = self._find_first_free_port(self.BASE_PORT, self._host)
log.info("Starting dashboard (listen_address=%s, port=%d)", self._host, port)
thread = threading.Thread(target=lambda: self.run(port=port), daemon=True)View on GitHub (pinned to 7fcbca7e62)
Solutions
- Find and stop the process holding the port (lsof -i :<port> / netstat) or kill the stale dashboard process
- Pass a different start_port when launching the dashboard
- Set the dashboard port explicitly in serena_config.yml to a known-free port
- Disable the dashboard (web_dashboard: false in config) if not needed
Example fix
// before --port 24282 # occupied // after serena start --port 24300 # or set web_dashboard start_port in serena_config.yml
Defensive patterns
Strategy: validation
Validate before calling
import socket
def is_port_free(port: int, host: str = "localhost") -> bool:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((host, port))
return True
except OSError:
return False
if not any(is_port_free(p) for p in range(start_port, start_port + 100)):
raise SystemExit(f"No free ports from {start_port}; free one or choose another range") Try / catch
try:
dashboard.run_in_thread(port)
except RuntimeError as e:
if "No free ports" in str(e):
port = find_alternate_port() # or disable dashboard
else:
raise Prevention
- Check port availability with a socket bind before starting
- Configure a distinct dashboard port per project in serena_config.yml
- Kill stale dashboard processes after crashes (lsof -i :<port>)
- Disable the web dashboard in CI/container environments
When it happens
Trigger: Calling Dashboard.run/run_in_thread when every port from start_port upward (within the scan range) is already bound, blocked by firewall, or lacks bind permission; another Serena/other-app instance already listening on the default port.
Common situations: Two Serena dashboard instances running concurrently; a stale process still holding the port; running in a container/CI where the port range is blocked; SELinux or non-root restrictions on low ports when start_port is small.
Related errors
- SHA256 checksum mismatch for vshaxe VSIX. Expected {expected
- Dashboard is not running.
- This method must be overridden for each subclass
- Context file not found: {path.resolve()}
- Cannot use both fixed_tools and excluded_tools/included_opti
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/8632c5b5fb326099.
Report an issue: GitHub.