{"record":{"id":"44826c123852bcbe","repo":"egametang/ET","slug":"actor-id-is-0-message","errorCode":null,"errorMessage":"actor id is 0: {message}","messagePattern":"actor id is 0: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.netinner/Scripts/Hotfix/Server/ProcessOuterSenderSystem.cs","lineNumber":194,"sourceCode":"            if (self.NeedException && ErrorCode.IsRpcNeedThrowException(response.Error))\n            {\n                self.SetException(new RpcException(response.Error, $\"Rpc error: actorId: {self.ActorId} request: {self.RequestType.FullName}, response: {response}\"));\n                return;\n            }\n\n            self.SetResult(response);\n        }\n\n        public static void Send(this ProcessOuterSender self, ActorId actorId, IMessage message)\n        {\n            self.SendInner(actorId, message as MessageObject);\n        }\n\n        private static void SendInner(this ProcessOuterSender self, ActorId actorId, MessageObject message)\n        {\n            if (actorId == default)\n            {\n                throw new Exception($\"actor id is 0: {message}\");\n            }\n            \n            if (message == null)\n            {\n                throw new Exception($\"message is null\");\n            }\n\n            // 如果发向同一个进程，则报错\n            if (actorId.Address == self.GetSingleton<AddressSingleton>().InnerAddress)\n            {\n                throw new Exception($\"actor is the same process: {actorId}\");\n            }\n            Session session = self.Get(actorId.Address);\n            session.Send(actorId.FiberInstanceId, message);\n        }\n\n        private static int GetRpcId(this ProcessOuterSender self)\n        {","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.netinner/Scripts/Hotfix/Server/ProcessOuterSenderSystem.cs#L176-L212","documentation":"ProcessOuterSender.SendInner refuses to send a message when actorId is default (zero). ProcessOuterSender is the cross-process outer channel — unlike the inner sender it never routes locally, so a zero id cannot be resolved to any session. This is a hard precondition check before a Session lookup and Send.","triggerScenarios":"Calling ProcessOuterSender.Send(actorId, message) with an ActorId that was never populated; resolving an address from a config/map that returned default for an unknown process.","commonSituations":"The caller assumed an outer process address exists but it was not configured in the start config; the ActorId field on an entity/component was not initialized before a send; a message was routed based on a player/guild id whose process mapping is missing.","solutions":["Log the actorId and its source (which config entry or look-up produced it) at the call site.","Confirm the target process is declared in the process/address configuration and its address is registered.","Guard the send with an actorId == default check and skip or queue the message."],"exampleFix":"// before\nouterSender.Send(actorId, msg);\n\n// after\nif (actorId == default)\n{\n    Log.Error($\"cannot Send, actorId is zero for {msg}\");\n    return;\n}\nouterSender.Send(actorId, msg);","handlingStrategy":"validation","validationCode":"if (actorId == default) { Log.Error($\"cannot Send, actorId is zero for {message}\"); return; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate ActorId is non-default before any ProcessOuterSender.Send.","Confirm the target process address is configured for the scene type.","Centralize address resolution so missing entries log clearly."],"tags":["et-framework","actor-rpc","validation","network"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}