{"record":{"id":"186f3ba761134850","repo":"egametang/ET","slug":"message-is-null","errorCode":null,"errorMessage":"message is null","messagePattern":"message is null","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.netinner/Scripts/Hotfix/Server/ProcessOuterSenderSystem.cs","lineNumber":199,"sourceCode":"\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        {\n            return ++self.RpcId;\n        }\n\n        public static async ETTask<IResponse> Call(this ProcessOuterSender self, ActorId actorId, IRequest iRequest, bool needException = true)\n        {","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.netinner/Scripts/Hotfix/Server/ProcessOuterSenderSystem.cs#L181-L217","documentation":"ProcessOuterSender.SendInner requires a non-null MessageObject. The public Send method casts the IMessage to MessageObject, and if that cast yields null (e.g. the IMessage is not a MessageObject subclass) the guard throws. This prevents sending an empty buffer over the outer channel.","triggerScenarios":"Passing a message object that does not inherit from MessageObject (so the `as` cast returns null); passing a literally null IMessage reference to Send.","commonSituations":"A message type was defined without the required MessageObject base class; a hand-constructed IMessage implementation that is not part of the ET message hierarchy; a code path that passes null because a Create() call failed or was skipped.","solutions":["Ensure the message type extends MessageObject / is a proper ET message (generated via the schema).","Add a null check before calling Send so the error is logged with context rather than thrown deep in the sender.","Verify the message was created via the framework's Create() factory rather than new'd directly."],"exampleFix":"// before\nouterSender.Send(actorId, msg as IMessage);\n\n// after\nif (msg is not MessageObject mo)\n{\n    Log.Error($\"message is null or not a MessageObject: {msg}\");\n    return;\n}\nouterSender.Send(actorId, mo);","handlingStrategy":"type-guard","validationCode":"if (message is not MessageObject) { Log.Error($\"message is null or not a MessageObject: {message}\"); return; }","typeGuard":"static bool IsValidMessage(IMessage msg) => msg is MessageObject;","tryCatchPattern":null,"preventionTips":["Ensure all message types derive from MessageObject via the schema generator.","Create messages through the framework Create() factory.","Add a null/type check before Send to fail with context."],"tags":["et-framework","validation","message","network"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}