rohitg00/ai-engineering-from-scratch · error · RuntimeError
{peer.name}: no mutually supported modern version
Error message
{peer.name}: no mutually supported modern version What it means
Discovery succeeded and advertised versions, but none of them intersect with the versions this client can speak, so _mutual_version returned None. The client will not pretend to speak a version it does not support.
Source
Thrown at phases/13-tools-and-protocols/08-building-an-mcp-client/code/main.py:433
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,
"server/discover",
{},
selected,View on GitHub (pinned to 39ea8a1c6d)
Solutions
- Compare the server's advertised versions with the client's supported set
- Upgrade the client's supported version list to include the server's revision
- Downgrade or reconfigure the server to advertise a common version
Example fix
// before
client = McpClient(..., supported_modern={"2.0"})
# server advertises ["2.1"]
// after
client = McpClient(..., supported_modern={"2.0", "2.1"}) Defensive patterns
Strategy: validation
Validate before calling
adv = probe_supported_versions(peer)
if not set(adv) & client.supported_modern:
widen_client_versions_or_upgrade_server(client, peer) Type guard
null
Try / catch
try:
client.connect_all()
except RuntimeError as e:
if "no mutually supported modern version" in str(e):
reconcile_version_sets(client, peer) Prevention
- Track server version sets in config and diff them at deploy time
- Upgrade client support before upgrading servers
When it happens
Trigger: _mutual_version(advertised) returns None: every entry in the server's supportedVersions list is absent from the client's supported modern versions.
Common situations: Major version skew after a server upgrade; client pinned to an old revision set; server advertising only prerelease versions the client excludes.
Related errors
- -32022
- -32022
- server/discover accepts no params beyond _meta
- {peer.name}: unsupported legacy protocol revision
- {peer.name}: malformed discovery response
AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26).
Data as JSON: /api/errors/c9b4db9b87e87c34.
Report an issue: GitHub.