rohitg00/ai-engineering-from-scratch · error · RuntimeError
{peer.name}: bounded legacy probe returned no result
Error message
{peer.name}: bounded legacy probe returned no result What it means
The legacy initialize probe completed but _send returned something that is not a dict (None, a string, a list, etc.), so there is no JSON-RPC message to decode. The client refuses to guess and aborts the legacy handshake for that peer.
Source
Thrown at phases/13-tools-and-protocols/08-building-an-mcp-client/code/main.py:373
raise RuntimeError(
f"{peer.name}: {trigger}; legacy compatibility is not allowlisted"
)
request_id = self._new_id()
initialize = legacy_request(
request_id,
"initialize",
{
"protocolVersion": self.supported_legacy[0],
"capabilities": self.client_capabilities.copy(),
"clientInfo": CLIENT_INFO.copy(),
},
)
try:
response = self._send(peer, initialize, self.legacy_probe_timeout_ms)
except (TimeoutError, ConnectionError) as exc:
raise RuntimeError(f"{peer.name}: bounded legacy probe failed closed") from exc
if not isinstance(response, dict):
raise RuntimeError(f"{peer.name}: bounded legacy probe returned no result")
kind, payload = decode_rpc_response(response, request_id)
if kind != "result":
raise RuntimeError(f"{peer.name}: legacy initialize returned an error")
result = payload
version = result.get("protocolVersion")
capabilities = result.get("capabilities")
server_info = result.get("serverInfo")
valid_server_info = (
isinstance(server_info, dict)
and isinstance(server_info.get("name"), str)
and bool(server_info["name"])
and isinstance(server_info.get("version"), str)
and bool(server_info["version"])
)
if version not in self.supported_legacy:
raise RuntimeError(f"{peer.name}: unsupported legacy protocol revision")
if not isinstance(capabilities, dict) or not valid_server_info:
raise RuntimeError(f"{peer.name}: malformed legacy initialize result")View on GitHub (pinned to 39ea8a1c6d)
Solutions
- Inspect what the transport actually returned for the initialize call
- Fix the transport to parse frames into dicts before returning
- Check the server logs for a crash during initialize
- In tests, make the fake transport return a JSON-RPC response dict
Example fix
// before
def fake_send(peer, msg, timeout):
return json.dumps({"jsonrpc": "2.0", "id": msg["id"], "result": {}})
// after
def fake_send(peer, msg, timeout):
return {"jsonrpc": "2.0", "id": msg["id"], "result": {}} Defensive patterns
Strategy: type-guard
Validate before calling
response = transport.peek_response(peer)
if not isinstance(response, dict):
fix_transport_parse() # before running connect_all Type guard
def is_rpc_message(value) -> bool:
return isinstance(value, dict) and ("result" in value or "error" in value) Try / catch
try:
client.connect_all()
except RuntimeError as e:
if "returned no result" in str(e):
log_transport_dump(peer) Prevention
- Unit-test transports to always return parsed dicts
- Add transport-level schema checks in CI
When it happens
Trigger: _probe_legacy gets a response from self._send(peer, initialize, ...) where isinstance(response, dict) is False — e.g. the transport returns None on close or a raw string payload.
Common situations: Buggy transport shim that returns the raw wire text instead of parsed JSON; server closing the connection mid-handshake so the reader yields None; a mock/fake transport in tests returning the wrong shape.
Related errors
- {peer.name}: malformed discovery response
- {peer.name}: proven-modern discovery retry returned no resul
- {peer.name}: missing response
- {peer.name}: {trigger}; legacy compatibility is not allowlis
- {peer.name}: bounded legacy probe failed closed
AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26).
Data as JSON: /api/errors/dd0d1a5cd3464abe.
Report an issue: GitHub.