{"record":{"id":"b1bae6f60663a56d","repo":"rohitg00/ai-engineering-from-scratch","slug":"peer-name-rpc-error-payload","errorCode":null,"errorMessage":"{peer.name}: RPC error {payload}","messagePattern":"(.+?): RPC error (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"phases/13-tools-and-protocols/08-building-an-mcp-client/code/main.py","lineNumber":491,"sourceCode":"        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\", {})\n                peer.tools = sorted(result.get(\"tools\", []), key=lambda tool: tool[\"name\"])\n\n    def merge(self, policy: str = \"prefix-on-collision\") -> None:\n        if policy not in {\"prefix-on-collision\", \"reject\"}:\n            raise ValueError(\"policy must be prefix-on-collision or reject\")\n        self.registry.clear()","sourceCodeStart":473,"sourceCodeEnd":509,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/phases/13-tools-and-protocols/08-building-an-mcp-client/code/main.py#L473-L509","documentation":"The peer answered a tools/list or tools/call request with a JSON-RPC error object. The client surfaces the error payload verbatim in the message so the caller can see the server's code and message.","triggerScenarios":"decode_rpc_response(response, request_id) in _request returns kind='error', i.e. the matched response carries an error, not a result.","commonSituations":"Calling a tool that does not exist on the peer; invalid tool arguments; server-side execution failure or permission denial.","solutions":["Read the embedded payload for the server's error code and message","Verify the tool name against the peer's discovered tools/list result","Check argument shape before calling","Fix the server-side cause if the error is a genuine execution failure"],"exampleFix":"// before\nclient.call(\"search\", {\"q\": 123})  # q must be a string\n\n// after\nclient.call(\"search\", {\"q\": \"hello\"})","handlingStrategy":"try-catch","validationCode":"names = {t['name'] for t in known_tools(peer)}\nif tool_name not in names:\n    raise ValueError(f'unknown tool {tool_name} for {peer.name}')","typeGuard":"null","tryCatchPattern":"try:\n    client.call(tool_name, args)\nexcept RuntimeError as e:\n    if \"RPC error\" in str(e):\n        handle_server_error(parse_payload(str(e)), tool_name)","preventionTips":["Discover tools first and validate names/args against the schema","Log the embedded error payload for diagnosis"],"tags":["mcp","rpc-error","tool-call"],"backgroundTag":"json-rpc-error-response","analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}