{"record":{"id":"34d4ffa05d503b8d","repo":"egametang/ET","slug":"rpc-error-request-actor-reply","errorCode":null,"errorMessage":"Rpc error: request, 注意Actor消息超时，请注意查看是否死锁或者没有reply: {request}, response: {response}","messagePattern":"Rpc error: request, 注意Actor消息超时，请注意查看是否死锁或者没有reply: (.+?), response: (.+?)","errorType":"exception","errorClass":"RpcException","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.login/Scripts/Hotfix/Client/Login/ClientSenderComponentSystem.cs","lineNumber":81,"sourceCode":"\n        public static void Send(this ClientSenderComponent self, IMessage message)\n        {\n            A2NetClient_Message a2NetClientMessage = A2NetClient_Message.Create();\n            a2NetClientMessage.MessageObject = message;\n            self.Root().GetComponent<ProcessInnerSender>().Send(self.FiberInstanceId, a2NetClientMessage);\n        }\n\n        public static async ETTask<IResponse> Call(this ClientSenderComponent self, IRequest request, bool needException = true)\n        {\n            A2NetClient_Request a2NetClientRequest = A2NetClient_Request.Create();\n            a2NetClientRequest.MessageObject = request;\n            \n            using A2NetClient_Response a2NetClientResponse = await self.Root().GetComponent<ProcessInnerSender>().Call(self.FiberInstanceId, a2NetClientRequest) as A2NetClient_Response;\n            IResponse response = a2NetClientResponse.MessageObject;\n            \n            if (response.Error == ErrorCode.ERR_MessageTimeout)\n            {\n                throw new RpcException(response.Error, $\"Rpc error: request, 注意Actor消息超时，请注意查看是否死锁或者没有reply: {request}, response: {response}\");\n            }\n\n            if (needException && ErrorCode.IsRpcNeedThrowException(response.Error))\n            {\n                throw new RpcException(response.Error, $\"Rpc error: {request}, response: {response}\");\n            }\n            return response;\n        }\n\n    }\n}\n","sourceCodeStart":63,"sourceCodeEnd":93,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.login/Scripts/Hotfix/Client/Login/ClientSenderComponentSystem.cs#L63-L93","documentation":"Thrown as RpcException when an Actor RPC call's response carries Error == ErrorCode.ERR_MessageTimeout. The Chinese text warns to check for deadlock or a missing reply handler. This means the request was sent but no response was received within the timeout window.","triggerScenarios":"ClientSenderComponent.Call sends a request via ProcessInnerSender to a target fiber; if the handler on the receiving side never replies (no Send(response) call), or if there is a deadlock preventing the reply, the timeout fires.","commonSituations":"The message handler on the server side processes the request but forgets to reply. A deadlock between fibers prevents the reply from being sent. The timeout is too short for the operation's actual latency. The target fiber crashed or was disposed before replying.","solutions":["Check that the handler for the request type actually sends a reply (response) — trace the handler from the request type's dispatch.","Look for deadlocks: circular awaits between fibers, or a fiber blocked on a synchronous call that prevents it from processing the reply.","Increase the RPC timeout if the operation legitimately takes longer than the default window.","Check server logs for the target fiber crashing or being disposed mid-request."],"exampleFix":"// before: handler processes request but doesn't reply\npublic static void OnMyRequest(MyRequest req)\n{\n    DoWork(req);\n    // missing reply\n}\n// after: always reply\npublic static async ETTask OnMyRequest(Session session, MyRequest req, MyResponse rsp, Action reply)\n{\n    DoWork(req);\n    reply();\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { IResponse resp = await self.Call(request); } catch (RpcException e) when (e.Error == ErrorCode.ERR_MessageTimeout) { Log.Error($\"RPC timeout for {request.GetType().Name}: {e.Message}\"); /* retry or fallback */ }","preventionTips":["Always ensure every RPC handler sends a reply — audit handlers during code review.","Avoid synchronous blocking calls inside fiber handlers that could cause deadlock.","Set appropriate timeouts based on the expected operation latency.","Monitor fiber health to detect crashed/disposed fibers that drop pending RPC replies."],"tags":["network","rpc","timeout","deadlock","login"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}