{"record":{"id":"bb9e6f5928f21fb6","repo":"rohitg00/ai-engineering-from-scratch","slug":"peer-name-trigger-legacy-compatibility-is-no","errorCode":null,"errorMessage":"{peer.name}: {trigger}; legacy compatibility is not allowlisted","messagePattern":"(.+?): (.+?); legacy compatibility is not allowlisted","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"phases/13-tools-and-protocols/08-building-an-mcp-client/code/main.py","lineNumber":355,"sourceCode":"    ) -> dict[str, Any] | None:\n        return peer.transport(message, timeout_ms)\n\n    def _mutual_version(self, advertised: list[Any]) -> str | None:\n        common = [version for version in advertised if version in self.supported_modern]\n        return sorted(common, reverse=True)[0] if common else None\n\n    def _activate_modern(self, peer: Peer, result: dict[str, Any], version: str) -> None:\n        if result.get(\"resultType\") != \"complete\":\n            raise RuntimeError(f\"{peer.name}: modern discovery omitted resultType\")\n        peer.era = \"modern\"\n        peer.protocol_version = version\n        peer.capabilities = result.get(\"capabilities\", {})\n        peer.server_info = result.get(\"_meta\", {}).get(SERVER_INFO_KEY, {})\n        peer.available = True\n\n    def _probe_legacy(self, peer: Peer, trigger: str) -> None:\n        if not peer.allow_legacy:\n            raise RuntimeError(\n                f\"{peer.name}: {trigger}; legacy compatibility is not allowlisted\"\n            )\n        request_id = self._new_id()\n        initialize = legacy_request(\n            request_id,\n            \"initialize\",\n            {\n                \"protocolVersion\": self.supported_legacy[0],\n                \"capabilities\": self.client_capabilities.copy(),\n                \"clientInfo\": CLIENT_INFO.copy(),\n            },\n        )\n        try:\n            response = self._send(peer, initialize, self.legacy_probe_timeout_ms)\n        except (TimeoutError, ConnectionError) as exc:\n            raise RuntimeError(f\"{peer.name}: bounded legacy probe failed closed\") from exc\n        if not isinstance(response, dict):\n            raise RuntimeError(f\"{peer.name}: bounded legacy probe returned no result\")","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/phases/13-tools-and-protocols/08-building-an-mcp-client/code/main.py#L337-L373","documentation":"Raised when the MCP client's fallback path tries to downgrade a peer to the legacy protocol but the peer was not configured with allow_legacy=True. The client treats legacy compatibility as an opt-in trust decision, so it fails closed instead of silently negotiating an older, less-verified protocol revision.","triggerScenarios":"Modern discovery on a peer returns an empty/unrecognized result or an unrecognized discovery error code, _connect_peer calls _probe_legacy(peer, trigger), and peer.allow_legacy is falsy.","commonSituations":"Pointing the client at an old MCP server that only speaks a legacy initialize handshake; forgetting to set allow_legacy in the Peer config; server upgrade changing discovery behavior so the legacy fallback path suddenly engages.","solutions":["Set allow_legacy=True on the Peer if you intentionally need to talk to the legacy server","Upgrade the peer server to a modern protocol revision that answers server/discover","Check why modern discovery failed (empty response, unrecognized error code) and fix the server side","Keep legacy off in production and treat this error as a signal the server is outdated"],"exampleFix":"// before\npeer = Peer(name=\"old-server\", transport=t)  # allow_legacy defaults to False\nclient.connect_all()  # -> RuntimeError: legacy compatibility is not allowlisted\n\n// after\npeer = Peer(name=\"old-server\", transport=t, allow_legacy=True)\nclient.connect_all()","handlingStrategy":"validation","validationCode":"for peer in client.peers.values():\n    if not peer.allow_legacy and peer_likely_legacy(peer):\n        peer.allow_legacy = True  # explicit opt-in before connect_all","typeGuard":"null","tryCatchPattern":"try:\n    client.connect_all()\nexcept RuntimeError as e:\n    if \"legacy compatibility is not allowlisted\" in str(e):\n        # decide: opt in to legacy or upgrade the peer\n        ...","preventionTips":["Declare legacy support per peer at configuration time, not at connect time","Keep a manifest of which peers speak which protocol era"],"tags":["mcp","protocol-negotiation","legacy","config"],"backgroundTag":"protocol-version-negotiation-failed","analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}