rohitg00/ai-engineering-from-scratch · error · RuntimeError

{peer.name}: malformed modern discovery result

Error message

{peer.name}: malformed modern discovery result

What it means

The peer answered server/discover with a result, but its supportedVersions field is not a list of strings. The client requires an explicit, well-typed version advertisement before it can pick a mutually supported revision.

Source

Thrown at phases/13-tools-and-protocols/08-building-an-mcp-client/code/main.py:430

        )
        try:
            response = self._send(peer, probe, self.discovery_timeout_ms)
        except (TimeoutError, ConnectionError) as exc:
            self._probe_legacy(peer, type(exc).__name__)
            return

        if response is None:
            self._probe_legacy(peer, "empty discovery response")
            return
        if not isinstance(response, dict):
            raise RuntimeError(f"{peer.name}: malformed discovery response")
        kind, payload = decode_rpc_response(response, request_id)
        if kind == "result":
            advertised = payload.get("supportedVersions", [])
            if not isinstance(advertised, list) or not all(
                isinstance(version, str) for version in advertised
            ):
                raise RuntimeError(f"{peer.name}: malformed modern discovery result")
            selected = self._mutual_version(advertised)
            if selected is None:
                raise RuntimeError(f"{peer.name}: no mutually supported modern version")
            self._activate_modern(peer, payload, selected)
            return

        code = payload["code"]
        if code in RECOGNIZED_MODERN_ERRORS:
            if code != -32022:
                raise RuntimeError(f"{peer.name}: correct modern request error {code} before retrying")
            data = payload.get("data")
            advertised = data.get("supported", []) if isinstance(data, dict) else []
            selected = self._mutual_version(advertised)
            if selected is None:
                raise RuntimeError(f"{peer.name}: no mutually supported modern version")
            retry_id = self._new_id()
            retry = modern_request(
                retry_id,

View on GitHub (pinned to 39ea8a1c6d)

Solutions

  1. Log the discovery result and inspect supportedVersions
  2. Fix the server to emit supportedVersions as an array of version strings
  3. Validate the server build against the modern discovery schema

Example fix

// before (server)
{"supportedVersions": ["1.1", 1.2]}

// after
{"supportedVersions": ["1.1", "1.2"]}
Defensive patterns

Strategy: validation

Validate before calling

adv = probe_supported_versions(peer)
if not (isinstance(adv, list) and all(isinstance(v, str) for v in adv)):
    fix_server_discovery_payload(peer)

Type guard

def valid_version_advertisement(v) -> bool:
    return isinstance(v, list) and all(isinstance(x, str) for x in v)

Try / catch

null

Prevention

When it happens

Trigger: decode_rpc_response returns kind='result' and payload.get('supportedVersions') is not a list, or contains entries that are not str.

Common situations: Server serializing versions as numbers or nulls; a typo'd field in a custom server build; a discovery payload built by hand in tests.

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


AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26). Data as JSON: /api/errors/d863b744b185ff8c. Report an issue: GitHub.