egametang/ET · error · RpcException
Rpc error: request, 注意Actor消息超时,请注意查看是否死锁或者没有reply: {request
Error message
Rpc error: request, 注意Actor消息超时,请注意查看是否死锁或者没有reply: {request}, response: {response} What it means
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.
Source
Thrown at Packages/cn.etetet.login/Scripts/Hotfix/Client/Login/ClientSenderComponentSystem.cs:81
public static void Send(this ClientSenderComponent self, IMessage message)
{
A2NetClient_Message a2NetClientMessage = A2NetClient_Message.Create();
a2NetClientMessage.MessageObject = message;
self.Root().GetComponent<ProcessInnerSender>().Send(self.FiberInstanceId, a2NetClientMessage);
}
public static async ETTask<IResponse> Call(this ClientSenderComponent self, IRequest request, bool needException = true)
{
A2NetClient_Request a2NetClientRequest = A2NetClient_Request.Create();
a2NetClientRequest.MessageObject = request;
using A2NetClient_Response a2NetClientResponse = await self.Root().GetComponent<ProcessInnerSender>().Call(self.FiberInstanceId, a2NetClientRequest) as A2NetClient_Response;
IResponse response = a2NetClientResponse.MessageObject;
if (response.Error == ErrorCode.ERR_MessageTimeout)
{
throw new RpcException(response.Error, $"Rpc error: request, 注意Actor消息超时,请注意查看是否死锁或者没有reply: {request}, response: {response}");
}
if (needException && ErrorCode.IsRpcNeedThrowException(response.Error))
{
throw new RpcException(response.Error, $"Rpc error: {request}, response: {response}");
}
return response;
}
}
}
View on GitHub (pinned to 5cab01f7a8)
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.
Example fix
// before: handler processes request but doesn't reply
public static void OnMyRequest(MyRequest req)
{
DoWork(req);
// missing reply
}
// after: always reply
public static async ETTask OnMyRequest(Session session, MyRequest req, MyResponse rsp, Action reply)
{
DoWork(req);
reply();
} Defensive patterns
Strategy: try-catch
Try / catch
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 */ } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Rpc error: {request}, response: {response}
- Rpc error: request, 注意Actor消息超时,请注意查看是否死锁或者没有reply: actorId:
- not found response type, request type: {request.FullName}
- router manager address is empty.
- get router fail: {netComponent.Root().Id} {address}
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/34d4ffa05d503b8d.
Report an issue: GitHub.