{"record":{"id":"b5c706d2540b268b","repo":"rohitg00/ai-engineering-from-scratch","slug":"peer-name-protocol-era-not-selected","errorCode":null,"errorMessage":"{peer.name}: protocol era not selected","messagePattern":"(.+?): protocol era not selected","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"phases/13-tools-and-protocols/08-building-an-mcp-client/code/main.py","lineNumber":485,"sourceCode":"\n    def connect_all(self) -> None:\n        for peer_name in sorted(self.peers):\n            self._connect_peer(self.peers[peer_name])\n\n    def _request(self, peer: Peer, method: str, params: dict[str, Any]) -> dict[str, Any]:\n        request_id = self._new_id()\n        if peer.era == \"modern\":\n            message = modern_request(\n                request_id,\n                method,\n                params,\n                peer.protocol_version or PROTOCOL_VERSION,\n                self.client_capabilities,\n            )\n        elif peer.era == \"legacy\":\n            message = legacy_request(request_id, method, params)\n        else:\n            raise RuntimeError(f\"{peer.name}: protocol era not selected\")\n        response = self._send(peer, message)\n        if not isinstance(response, dict):\n            raise RuntimeError(f\"{peer.name}: missing response\")\n        kind, payload = decode_rpc_response(response, request_id)\n        if kind != \"result\":\n            raise RuntimeError(f\"{peer.name}: RPC error {payload}\")\n        result = dict(payload)\n        if peer.era == \"modern\" and \"resultType\" not in result:\n            raise RuntimeError(f\"{peer.name}: modern result omitted resultType\")\n        if peer.era == \"legacy\":\n            result.setdefault(\"resultType\", \"complete\")\n        return result\n\n    def discover_tools(self) -> None:\n        for peer_name in sorted(self.peers):\n            peer = self.peers[peer_name]\n            if peer.available:\n                result = self._request(peer, \"tools/list\", {})","sourceCodeStart":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/phases/13-tools-and-protocols/08-building-an-mcp-client/code/main.py#L467-L503","documentation":"A request was attempted against a peer whose era field is neither 'modern' nor 'legacy', meaning connect_all never completed handshake/activation for that peer. The client refuses to guess a wire format and aborts before serializing anything.","triggerScenarios":"discover_tools or call is invoked on a peer where peer.era is unset because _activate_modern/_probe_legacy never ran or failed (e.g. connect_all skipped, or an earlier connect error was swallowed).","commonSituations":"Calling discover_tools/call before connect_all; swallowing a connect_all exception per-peer and then continuing; resetting peer state manually.","solutions":["Ensure connect_all() runs to completion before discover_tools()/call()","Don't swallow per-peer connect errors — check peer.available first","Re-run the handshake for the failed peer","Guard calls with a check on peer.era/peer.available"],"exampleFix":"// before\ntry:\n    client.connect_all()\nexcept RuntimeError:\n    pass\nclient.discover_tools()  # era never selected\n\n// after\nclient.connect_all()\nif not all(p.available for p in client.peers.values()):\n    raise SystemExit(\"some peers failed to connect\")\nclient.discover_tools()","handlingStrategy":"validation","validationCode":"assert all(p.available for p in client.peers.values()), 'run connect_all first'\nclient.discover_tools()","typeGuard":"def peer_ready(peer) -> bool:\n    return peer.era in {'modern', 'legacy'} and peer.available","tryCatchPattern":"null","preventionTips":["Never swallow connect_all exceptions","Gate request calls on peer.available"],"tags":["mcp","lifecycle","state-machine"],"backgroundTag":"invalid-state-transition","analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}