CoplayDev/unity-mcp · error · TimeoutError
Timeout receiving Unity response
Error message
Timeout receiving Unity response
What it means
Raised in the framed receive loop (unity_connection.py:206): a socket.timeout while reading the header or payload is caught and re-raised as TimeoutError('Timeout receiving Unity response'). Unlike error 183 (too many heartbeats), this means the socket itself went silent — no bytes at all within the configured timeout.
Source
Thrown at Server/src/transport/legacy/unity_connection.py:206
if payload_len == 0:
heartbeat_count += 1
logger.debug(
f"Received heartbeat frame #{heartbeat_count}")
if heartbeat_count >= heartbeat_limit or (time.monotonic() - heartbeat_started) > heartbeat_window:
raise TimeoutError(
"Unity sent heartbeat frames without payload within configured threshold"
)
continue
if payload_len > FRAMED_MAX:
raise ValueError(
f"Invalid framed length: {payload_len}")
payload = self._read_exact(sock, payload_len)
logger.debug(
f"Received framed response ({len(payload)} bytes)")
return payload
except socket.timeout as exc:
logger.warning("Socket timeout during framed receive")
raise TimeoutError("Timeout receiving Unity response") from exc
except TimeoutError:
raise
except Exception as exc:
logger.error(f"Error during framed receive: {exc}")
raise
chunks = []
# Respect the socket's currently configured timeout
try:
while True:
chunk = sock.recv(buffer_size)
if not chunk:
if not chunks:
raise Exception(
"Connection closed before receiving data")
break
chunks.append(chunk)
View on GitHub (pinned to c21bf496bc)
Solutions
- Raise UNITY_MCP_CONNECTION_TIMEOUT (and/or framed_receive_timeout) if the command legitimately needs longer.
- Confirm Unity is responsive (not frozen on a dialog / infinite loop).
- Rely on send_command retry to reconnect and re-attempt.
Example fix
// before # UNITY_MCP_CONNECTION_TIMEOUT unset (300s) but framed recv stalls sooner // after export UNITY_MCP_CONNECTION_TIMEOUT=600
Defensive patterns
Strategy: retry
Validate before calling
import os
def framed_recv_timeout_adequate(estimated_seconds: float) -> bool:
return float(os.environ.get('UNITY_MCP_CONNECTION_TIMEOUT', 300)) >= estimated_seconds Type guard
def is_framed_recv_timeout(e: BaseException) -> bool:
return (isinstance(e, TimeoutError)
and str(e) == 'Timeout receiving Unity response') Try / catch
try:
resp = conn.send_command(cmd, params)
except TimeoutError as e:
if str(e) == 'Timeout receiving Unity response':
conn.disconnect() # clear possibly-stale socket
resp = conn.send_command(cmd, params) # retry once
else:
raise Prevention
- Set UNITY_MCP_CONNECTION_TIMEOUT high enough for your heaviest command.
- Confirm Unity is responsive (no frozen UI) before issuing long ops.
- Let send_command retry rather than hand-rolling a single raw receive.
When it happens
Trigger: receive_full_response in framing mode where Unity stops sending entirely (frozen UI, hard deadlock, no heartbeats either), or a single recv exceeding connection_timeout / framed_receive_timeout.
Common situations: Unity editor frozen (spinning beachball / not responding), a network stall, or connection_timeout set too low for a legitimately heavy command.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Connection closed before reading expected bytes
- Unity sent heartbeat frames without payload within configure
- Command '{command_type}' exceeded total deadline of {total_t
- Preview loading timed out.
- Connection to Unity timed out after {timeout or cfg.timeout}
AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13).
Data as JSON: /api/errors/dac50647cae4b14a.
Report an issue: GitHub.