rohitg00/ai-engineering-from-scratch · error · RuntimeError
{peer.name}: modern result omitted resultType
Error message
{peer.name}: modern result omitted resultType What it means
A modern-era request returned a successful result, but the result object lacks the required resultType field. The modern protocol mandates an explicit completion marker; only legacy results get a defaulted 'complete'. Its absence means the server is not conformant with the modern result schema.
Source
Thrown at phases/13-tools-and-protocols/08-building-an-mcp-client/code/main.py:494
request_id,
method,
params,
peer.protocol_version or PROTOCOL_VERSION,
self.client_capabilities,
)
elif peer.era == "legacy":
message = legacy_request(request_id, method, params)
else:
raise RuntimeError(f"{peer.name}: protocol era not selected")
response = self._send(peer, message)
if not isinstance(response, dict):
raise RuntimeError(f"{peer.name}: missing response")
kind, payload = decode_rpc_response(response, request_id)
if kind != "result":
raise RuntimeError(f"{peer.name}: RPC error {payload}")
result = dict(payload)
if peer.era == "modern" and "resultType" not in result:
raise RuntimeError(f"{peer.name}: modern result omitted resultType")
if peer.era == "legacy":
result.setdefault("resultType", "complete")
return result
def discover_tools(self) -> None:
for peer_name in sorted(self.peers):
peer = self.peers[peer_name]
if peer.available:
result = self._request(peer, "tools/list", {})
peer.tools = sorted(result.get("tools", []), key=lambda tool: tool["name"])
def merge(self, policy: str = "prefix-on-collision") -> None:
if policy not in {"prefix-on-collision", "reject"}:
raise ValueError("policy must be prefix-on-collision or reject")
self.registry.clear()
for peer_name in sorted(self.peers):
peer = self.peers[peer_name]
for tool in peer.tools:View on GitHub (pinned to 39ea8a1c6d)
Solutions
- Inspect the raw result to confirm resultType is missing
- Fix the modern server to always include resultType in results
- Verify no intermediary strips unknown fields
- If the server cannot be fixed, treat it as legacy (allow_legacy) so the default applies
Example fix
// before (server)
return {"jsonrpc": "2.0", "id": rid, "result": {"output": "ok"}}
// after
return {"jsonrpc": "2.0", "id": rid, "result": {"output": "ok", "resultType": "complete"}} Defensive patterns
Strategy: validation
Validate before calling
null
Type guard
def is_modern_result(result) -> bool:
return isinstance(result, dict) and 'resultType' in result Try / catch
try:
client.call(tool_name, args)
except RuntimeError as e:
if "omitted resultType" in str(e):
flag_server_conformance(peer.name) Prevention
- Contract-test modern servers to always emit resultType
- Gate servers on conformance checks before adding them as peers
When it happens
Trigger: peer.era == 'modern', decode_rpc_response returned a result dict, and 'resultType' not in result.
Common situations: Modern server build omitting resultType; partial server implementation; a gateway stripping fields from results.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- {peer.name}: malformed legacy initialize result
- {peer.name}: malformed modern discovery result
- -32600
- -32022
- -32603
AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26).
Data as JSON: /api/errors/9d69de6a5c6e1f07.
Report an issue: GitHub.