{"record":{"id":"2c8cca101845c648","repo":"egametang/ET","slug":"err-servicenotfound","errorCode":"ERR_ServiceNotFound","errorMessage":"route service not found in local cache sceneType: {sceneTypeName}","messagePattern":"route service not found in local cache sceneType: (.+?)","errorType":"exception","errorClass":"RpcException","httpStatus":null,"severity":"warning","filePath":"Packages/cn.etetet.servicediscovery/Scripts/Hotfix/Server/ServiceDiscoveryProxySystem.cs","lineNumber":410,"sourceCode":"                    }\n\n                    if (!ShouldRetryServiceCallError(rpcException.Error) || retryCount >= self.ServiceResolveRetryTimes)\n                    {\n                        throw;\n                    }\n\n                    await self.WaitResolveRetryDelayAsync();\n                }\n            }\n        }\n\n        private static ActorId ResolveServiceActorIdByRouteKeyOnce(this ServiceDiscoveryProxy self, int sceneType, string sceneTypeName,\n            long routeKey)\n        {\n            List<ServiceInfo> localServices = self.GetBySceneType(sceneType);\n            if (localServices.Count == 0)\n            {\n                throw new RpcException(ErrorCode.ERR_ServiceNotFound,\n                    $\"route service not found in local cache sceneType: {sceneTypeName}\");\n            }\n\n            return SelectServiceActorIdByRouteKey(localServices, routeKey, sceneTypeName);\n        }\n\n        private static bool ShouldRetryResolveService(this ServiceDiscoveryProxy self, RpcException rpcException)\n        {\n            return rpcException.Error == ErrorCode.ERR_ServiceNotFound\n                   || ServiceDiscoveryErrorHelper.ShouldTriggerFailover(rpcException.Error);\n        }\n\n        private static bool ShouldRetryServiceCallError(int error)\n        {\n            return error == ErrorCode.ERR_ServiceNotFound\n                   || ServiceDiscoveryErrorHelper.ShouldTriggerFailover(error);\n        }\n","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.servicediscovery/Scripts/Hotfix/Server/ServiceDiscoveryProxySystem.cs#L392-L428","documentation":"RpcException with code ERR_ServiceNotFound thrown at line 410 in ResolveServiceActorIdByRouteKeyOnce: the proxy's local service cache has zero entries for the requested sceneType. Because no instance is known locally, the route-key selection cannot proceed. ResolveServiceActorIdByRouteKeyAsync wraps this in a retry loop (up to ServiceResolveRetryTimes) with backoff; if still empty, it propagates.","triggerScenarios":"ResolveServiceActorIdByRouteKeyAsync/CallBySceneTypeAsync is called for a sceneType whose services have not been registered with (or discovered by) this proxy yet — GetBySceneType(sceneType).Count == 0. The proxy must have a subscribed/refreshed local cache containing at least one instance.","commonSituations":"The target service scene has not started/registered; the proxy has not subscribed to that sceneType or its subscription snapshot is empty/stale; startup ordering where the caller resolves before services publish; the sceneType int is wrong/mismatched so no service matches.","solutions":["Ensure the target service scene is running and has registered with discovery before resolving.","Confirm the proxy has subscribed to the sceneType and its local cache is populated (check subscribe/refresh timing).","Verify the sceneType argument maps to a real registered scene (SceneTypeSingleton.Instance.GetSceneName).","Delay/queue the resolve until discovery notifies the proxy that services for the sceneType exist."],"exampleFix":"// before\nActorId id = await proxy.ResolveServiceActorIdByRouteKeyAsync(sceneType, routeKey);\n\n// after: ensure cache is populated, then resolve\nif (proxy.GetBySceneType(sceneType).Count == 0)\n{\n    await proxy.SubscribeServiceChangeAsync(/* filter for sceneType */);\n    // optionally wait for notification\n}\nActorId id = await proxy.ResolveServiceActorIdByRouteKeyAsync(sceneType, routeKey);","handlingStrategy":"validation","validationCode":"// Ensure the proxy has at least one cached instance before resolving.\nList<ServiceInfo> services = proxy.GetBySceneType(sceneType);\nif (services.Count == 0)\n{\n    // subscribe/refresh first, then resolve\n    await proxy.SubscribeServiceChangeAsync(BuildFilterForSceneType(sceneType));\n    services = proxy.GetBySceneType(sceneType);\n    if (services.Count == 0)\n    {\n        Log.Warning($\"no service registered for sceneType {sceneType}\");\n        return default;\n    }\n}","typeGuard":"public static bool HasCachedService(ServiceDiscoveryProxy proxy, int sceneType)\n{\n    return proxy != null && proxy.GetBySceneType(sceneType).Count > 0;\n}","tryCatchPattern":"catch (RpcException e) when (e.Error == ErrorCode.ERR_ServiceNotFound)\n{\n    // no local instance; subscribe and retry, or degrade\n    Log.Warning($\"service not found for sceneType {sceneType}: {e.Message}\");\n}","preventionTips":["Start and register target service scenes before callers resolve them.","Subscribe the proxy to the relevant sceneType and wait for the first snapshot.","Verify the sceneType argument matches a registered scene name.","Queue/delay resolves until discovery confirms services exist."],"tags":["csharp","et-framework","service-discovery","proxy","caching","registration","startup-ordering"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}