egametang/ET · error · RpcException

Rpc error: actorId: {actorId} {request}, response: {response

Error message

Rpc error: actorId: {actorId} {request}, response: {response}

What it means

A generic RPC failure: the response carried a non-zero error code that ErrorCode.IsRpcNeedThrowException considers fatal, and needException was true (the default). Unlike the timeout case (241) this covers all other serious RPC error codes — the response came back but reported an error the framework treats as unrecoverable. The message includes the actorId, request, and response for diagnosis.

Source

Thrown at Packages/cn.etetet.netinner/Scripts/Hotfix/Server/MessageSenderSystem.cs:72

            {
                // 发给NetInner纤程
                A2NetInner_Request a2NetInner_Request = A2NetInner_Request.Create();
                a2NetInner_Request.ActorId = actorId;
                a2NetInner_Request.MessageObject = request;

                FiberInstanceId netInnerFiberInstanceId = self.GetSingleton<ProcessFiberAddressSingleton>().Get(SceneType.NetInner);
                using A2NetInner_Response a2NetInnerResponse = await self.ProcessInnerSender.Call(
                    netInnerFiberInstanceId, a2NetInner_Request, timeout) as A2NetInner_Response;
                response = a2NetInnerResponse.MessageObject;
            }

            if (response.Error == ErrorCode.ERR_MessageTimeout)
            {
                throw new RpcException(response.Error, $"Rpc error: request, 注意Actor消息超时,请注意查看是否死锁或者没有reply: actorId: {actorId} {request}, response: {response}");
            }
            if (needException && ErrorCode.IsRpcNeedThrowException(response.Error))
            {
                throw new RpcException(response.Error, $"Rpc error: actorId: {actorId} {request}, response: {response}");
            }
            return response;
        }
    }
}

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Inspect response.Error in the exception message to identify the specific error code, then look up its meaning in ErrorCode.
  2. If the failure is an expected/optional outcome, pass needException: false and check response.Error yourself.
  3. Fix the remote handler that is producing the error code (check its logs for the original exception).
  4. Verify request/response message definitions match between caller and handler assemblies (no stale generated code).

Example fix

// before — default throws on any serious error
var resp = await MessageSender.Instance.Call(actorId, request);

// after — tolerate expected errors for optional lookups
var resp = await MessageSender.Instance.Call(actorId, request, needException: false);
if (resp.Error != ErrorCode.ERR_OK)
{
    // handle gracefully
    return default;
}
Defensive patterns

Strategy: try-catch

Try / catch

var resp = await sender.Call(actorId, request, needException: false);
if (resp.Error != ErrorCode.ERR_OK) { /* handle expected failure */ }

Prevention

When it happens

Trigger: The remote handler explicitly set a non-zero error on the response (e.g. entity not found, permission denied, internal error); the inner transport returned a transport-level error code; the target fiber threw an exception that was serialized into the response error code.

Common situations: Calling a scene/fiber whose handler logic returns an error for the given input (invalid id, missing config); version mismatch where the request/response contract changed; the caller passed needException=true (default) for a call that is expected to fail occasionally and should have used needException=false.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/487d6340a345ef86. Report an issue: GitHub.