CoplayDev/unity-mcp · error · ConnectionError
Cannot reach {url}: {e}
Error message
Cannot reach {url}: {e} What it means
Raised by _fetch_url_full (unity_docs.py:100) when urllib's urlopen throws a URLError fetching a Unity ScriptReference page. HTTP-level failures (404, 500) are caught separately as HTTPError and returned as a status code, so this error is strictly transport-level: DNS resolution failure, connection refused, no route to host, or the 10s urlopen timeout expiring with no response.
Source
Thrown at Server/src/services/tools/unity_docs.py:100
async def _fetch_url_full(url: str) -> tuple[int, str, str]:
"""Fetch a URL and return (status_code, body_text, final_url).
Like _fetch_url but also returns the final URL after any redirects.
"""
loop = asyncio.get_running_loop()
def _do_fetch() -> tuple[int, str, str]:
req = Request(url, headers={"User-Agent": "MCPForUnity/1.0"})
try:
with urlopen(req, timeout=10) as resp:
body = resp.read().decode("utf-8", errors="replace")
return (resp.status, body, resp.url)
except HTTPError as e:
return (e.code, "", url)
except URLError as e:
raise ConnectionError(f"Cannot reach {url}: {e}") from e
return await loop.run_in_executor(None, _do_fetch)
# ---------------------------------------------------------------------------
# HTML parser
# ---------------------------------------------------------------------------
class _UnityDocParser(HTMLParser):
"""Extracts structured data from Unity ScriptReference HTML pages."""
def __init__(self) -> None:
super().__init__()
# Tracking state
self._in_subsection = False
self._subsection_depth = 0
self._subsection_title: str | None = None
self._in_signature = FalseView on GitHub (pinned to c21bf496bc)
Solutions
- Verify the host can reach docs.unity3d.com (curl -I https://docs.unity3d.com/ScriptReference/index.html) and configure HTTP(S)_PROXY if a proxy is required.
- Retry the call once or twice — URLError is often transient (DNS hiccup, momentary reset).
- Confirm DNS resolves docs.unity3d.com and that no firewall is dropping port 443.
- If running fully offline, disable/skip docs tools rather than letting every lookup throw.
Example fix
// before
status, body = await _fetch_url(url)
// after — tolerate transient reachability failures at the caller
try:
status, body = await _fetch_url(url)
except ConnectionError as e:
return {"status": "unavailable", "detail": str(e)} Defensive patterns
Strategy: retry
Validate before calling
# Pre-flight reachability check before fetching docs
import socket
from urllib.parse import urlparse
def can_reach(url: str, timeout: float = 3.0) -> bool:
host = urlparse(url).hostname
try:
socket.gethostbyname(host)
with socket.create_connection((host, 443), timeout=timeout):
return True
except OSError:
return False Type guard
def is_connection_error(e: BaseException) -> bool:
return isinstance(e, ConnectionError) and 'Cannot reach' in str(e) Try / catch
from services.tools.unity_docs import _fetch_url
for attempt in range(3):
try:
status, body = await _fetch_url(url)
break
except ConnectionError as e:
if attempt == 2:
return {"status": "unavailable", "detail": str(e)}
await asyncio.sleep(0.5 * (attempt + 1)) Prevention
- Run docs tools in an environment with outbound HTTPS to docs.unity3d.com.
- Configure HTTP_PROXY/HTTPS_PROXY in corporate networks before starting the server.
- Cache doc lookups so transient blips don't repeat-fetch the same URL.
When it happens
Trigger: Calling any unity_docs tool (e.g. get_unity_docs / member lookup) that builds a https://docs.unity3d.com/.../ScriptReference URL and calls _fetch_url/_fetch_url_full while the host has no network path to docs.unity3d.com.
Common situations: Sandboxed/offline CI, a corporate proxy or firewall blocking unity3d.com, a transient DNS or connectivity blip, or a wrong/outdated version segment in the URL that still resolves to a host that drops the connection (note: a real 404 is an HTTPError and does NOT trigger this).
Related errors
- Port must be positive.
- Port {port} is already in use.
- No available ports found in range {DefaultPort}-{DefaultPort
- fal submit returned no request_id: {truncated_response}
- fal {phase} failed (status={res?.Status}): {detail}
AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13).
Data as JSON: /api/errors/238bf13cfde01348.
Report an issue: GitHub.