CoplayDev/unity-mcp · error · ValueError
Invalid framed length: {payload_len}
Error message
Invalid framed length: {payload_len} What it means
Raised in the framed receive loop (unity_connection.py:198) when the 8-byte big-endian length prefix decodes to a value greater than FRAMED_MAX (64 MiB). This is a defensive guard against a corrupted or misaligned stream that would otherwise trigger a huge allocation.
Source
Thrown at Server/src/transport/legacy/unity_connection.py:198
heartbeat_limit = getattr(config, 'max_heartbeat_frames', 16)
heartbeat_window = getattr(config, 'heartbeat_timeout', 2.0)
heartbeat_started = time.monotonic()
heartbeat_count = 0
try:
while True:
header = self._read_exact(sock, 8)
payload_len = struct.unpack('>Q', header)[0]
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:View on GitHub (pinned to c21bf496bc)
Solutions
- Verify the Python server and MCPForUnity Unity package are on compatible versions (both must agree on framing).
- Ensure only one client owns the stdio port — new stdio connections stomp old ones.
- Drop the socket and reconnect to re-synchronize the stream (send_command does this on retry).
Example fix
// before — shared port, mixed traffic corrupts the framed stream // after — one owner per port; reconnect to resync conn.disconnect() conn.connect()
Defensive patterns
Strategy: try-catch
Validate before calling
FRAMED_MAX = 64 * 1024 * 1024
def framed_length_plausible(length: int) -> bool:
return 0 <= length <= FRAMED_MAX Type guard
def is_invalid_framed_length(e: BaseException) -> bool:
return isinstance(e, ValueError) and 'Invalid framed length' in str(e) Try / catch
try:
data = conn.receive_full_response(conn.sock)
except ValueError as e:
if 'Invalid framed length' in str(e):
# stream desync — drop socket, reconnect to resync
conn.disconnect()
conn.connect()
data = conn.receive_full_response(conn.sock)
else:
raise Prevention
- Run matched server + Unity package versions so framing is agreed on both sides.
- Ensure a single client owns the stdio port (stdio connections stomp each other).
- Reconnect after any protocol error rather than continuing on a desynced stream.
When it happens
Trigger: receive_full_response reads a length prefix that is garbage — protocol desync, a peer writing raw plaintext onto a connection that negotiated framing, or memory/stream corruption producing an absurd length.
Common situations: Version/transport mismatch where one side frames and the other sends legacy plaintext, a partial read making the 8 header bytes line up wrong, or two clients stomping the same stdio port.
Related errors
- MCP for Unity requires FRAMING=1, got: {text!r}
- Connection closed before reading expected bytes
- Unity sent heartbeat frames without payload within configure
- Timeout receiving Unity response
- Ping unsuccessful
AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13).
Data as JSON: /api/errors/cda99d517a337be8.
Report an issue: GitHub.