{"record":{"id":"6ec23c8d6780689f","repo":"egametang/ET","slug":"service-discovery-response-type-mismatch-request","errorCode":null,"errorMessage":"service discovery response type mismatch, request: {requestName}, actual: {rawResponse?.GetType().Name}","messagePattern":"service discovery response type mismatch, request: (.+?), actual: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.servicediscovery/Scripts/Hotfix/Server/ServiceDiscoveryAgentSystem.cs","lineNumber":628,"sourceCode":"                    }\n\n                    continue;\n                }\n\n                ActorId targetActorId = self.ServiceDiscoveryActorId;\n                try\n                {\n                    IResponse rawResponse = await self.MessageSender.Call(targetActorId, request);\n                    self = selfRef;\n                    if (self == null)\n                    {\n                        throw new Exception(\"service discovery agent disposed\");\n                    }\n\n                    if (rawResponse is not T response)\n                    {\n                        (rawResponse as MessageObject)?.Dispose();\n                        throw new Exception(\n                            $\"service discovery response type mismatch, request: {requestName}, actual: {rawResponse?.GetType().Name}\");\n                    }\n\n                    if (response.Error != ErrorCode.ERR_Success)\n                    {\n                        int error = response.Error;\n                        string message = response.Message;\n                        if (response is MessageObject messageObject)\n                        {\n                            messageObject.Dispose();\n                        }\n                        throw new RpcException(error,\n                            $\"service discovery response error, request: {requestName}, error: {error}, message: {message}\");\n                    }\n\n                    return response;\n                }\n                catch (Exception e)","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.servicediscovery/Scripts/Hotfix/Server/ServiceDiscoveryAgentSystem.cs#L610-L646","documentation":"Thrown at line 628 in ForwardToDiscoveryByFailoverCore: the master returned a response whose runtime type is not the expected T (the strongly-typed response the caller requested). The raw response is disposed and the call aborts. This indicates a contract/serialization mismatch between what the caller expects and what the master (or the routing layer) actually returned.","triggerScenarios":"ForwardToDiscoveryByFailover<T> is called with a T that does not match the response type the master produces for that request; an error/exception response object was returned instead of the success response; partial deployment where master and agent run different code versions with changed message definitions.","commonSituations":"Version skew between client and server message assemblies; a request routed to the wrong handler returning a different response type; proto/regeneration out of sync so the response class identity differs across processes.","solutions":["Ensure all processes run the same version of the service-discovery message assembly (rebuild and redeploy together).","Confirm the request type maps to the expected response type T at the call site.","Regenerate protocol/proto definitions and verify the response class is identical across client and master."],"exampleFix":"// before: T does not match the request's actual response type\nvar resp = await agent.ForwardToDiscoveryByFailover<WrongResponse>(req, name);\n\n// after: use the response type paired with the request\nvar resp = await agent.ForwardToDiscoveryByFailover<ServiceRegisterResponse>(req, name);","handlingStrategy":"type-guard","validationCode":"// Ensure the response type matches the request's contract before calling.\nType expected = ServiceDiscoveryProtocol.GetResponseType(req.GetType());\nif (!expected.IsAssignableFrom(typeof(T)))\n{\n    throw new InvalidOperationException($\"Response type {typeof(T)} does not match request {req.GetType()}\");\n}","typeGuard":"public static bool IsExpectedResponse<TRequest, TResponse>()\n    where TResponse : class, IResponse\n{\n    return typeof(TResponse) == ServiceDiscoveryProtocol.GetResponseType(typeof(TRequest));\n}","tryCatchPattern":"catch (Exception e) when (e.Message.Contains(\"response type mismatch\"))\n{\n    Log.Error($\"discovery response contract mismatch - redeploy matching versions: {e.Message}\");\n    // trigger coordinated redeploy\n}","preventionTips":["Deploy all processes with the same message assembly version.","Regenerate protocol definitions in lockstep across services.","Add a startup version-check between agent and master."],"tags":["csharp","et-framework","service-discovery","rpc","serialization","versioning","type-mismatch"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}