oraios/serena · error · ConnectionError
ProjectServer health check failed: {e}
Error message
ProjectServer health check failed: {e} What it means
Companion to the heartbeat check in ProjectServerClient.__init__: when the server responds but with a non-2xx status (raise_for_status) or another requests error (timeout, TLS, DNS), the constructor raises ConnectionError with the underlying exception message.
Source
Thrown at src/serena/project_server.py:175
"""
def __init__(self, host: str = "127.0.0.1", port: int = ProjectServer.PORT, timeout: int = 300) -> None:
"""
:param host: the host address of the project server.
:param port: the port of the project server.
:raises ConnectionError: if the project server is not reachable.
"""
self._base_url = f"http://{host}:{port}"
self._timeout = timeout
# verify that the server is running
try:
response = requests_lib.get(f"{self._base_url}/heartbeat", timeout=5)
response.raise_for_status()
except requests_lib.ConnectionError:
raise ConnectionError(f"ProjectServer is not reachable at {self._base_url}. Make sure the server is running.")
except requests_lib.RequestException as e:
raise ConnectionError(f"ProjectServer health check failed: {e}")
def query_project(self, project_name: str, tool_name: str, tool_params_json: str) -> str:
"""
Query a project by executing a Serena tool in its context.
The interface matches :meth:`QueryProjectTool.apply
<serena.tools.query_project_tools.QueryProjectTool.apply>`.
:param project_name: the name of the project to query.
:param tool_name: the name of the tool to execute. The tool must be read-only.
:param tool_params_json: the parameters to pass to the tool, encoded as a JSON string.
:return: the tool's result as a string.
"""
payload = QueryProjectRequest(
project_name=project_name,
tool_name=tool_name,
tool_params_json=tool_params_json,
).model_dump()View on GitHub (pinned to 7fcbca7e62)
Solutions
- Read the wrapped exception message for the root cause (status code vs timeout)
- Confirm the URL scheme matches the server (http vs https) and that /heartbeat is accessible (curl it)
- Increase timeout or retry after checking server logs for errors during startup
- Bypass or configure proxies (NO_PROXY) if a corporate proxy is intercepting localhost traffic
Example fix
// before
client = ProjectServerClient("https://localhost:24282") # server is plain http
// after
client = ProjectServerClient("http://localhost:24282") Defensive patterns
Strategy: retry
Validate before calling
r = requests.get(f"{base_url}/heartbeat", timeout=5)
assert r.ok, f"heartbeat status {r.status_code}" Try / catch
try:
client = ProjectServerClient(base_url)
except ConnectionError as e:
log.error("health check failed: %s", e)
client = retry_with_backoff(lambda: ProjectServerClient(base_url)) Prevention
- Match URL scheme to the server (http vs https)
- Set NO_PROXY for localhost to avoid proxy interception
- Check server logs for 5xx causes; increase timeout for slow starts
When it happens
Trigger: Server listening but /heartbeat returning 4xx/5xx (proxy interception, auth layer, misrouted path); request timeout because the server is overloaded; HTTPS base_url against a plain-HTTP server; DNS name not resolving.
Common situations: Reverse proxies or corporate proxies returning 403/502 for /heartbeat; using https:// when the server serves http://; transient network flakiness in CI causing timeouts.
Related errors
- Failed to connect to Serena service at {url}: {e}
- Request to {url} timed out: {e}
- API request failed with HTTP error: {e}
- Request failed: {e}
- Error downloading file.
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/824234ea2dd3efed.
Report an issue: GitHub.