egametang/ET · error · Exception
location db manager not found scene: {root.Name}
Error message
location db manager not found scene: {root.Name} What it means
Thrown by SelectServiceActorIdByRouteKey when the service list passed to route-key selection is null or empty. It is wrapped as RpcException(ERR_ServiceNotFound) so the CallBySceneTypeAsync retry loop (ShouldRetryServiceCallError returns true for ERR_ServiceNotFound) can trigger failover. It is the routing layer's invariant that at least one service instance exists before computing a consistent-hash index via GetRouteIndex.
Source
Thrown at Packages/cn.etetet.actorlocation/Scripts/Hotfix/Server/LocationComponentSystem.cs:138
self.RemoveCachedInfo(key);
return;
}
LocationInfo locationInfo = self.GetCachedInfo(key) ?? self.CreateInfo(key);
locationInfo.TypeStates.Clear();
foreach ((int locationType, LocationTypeState state) in snapshot)
{
locationInfo.TypeStates[locationType] = state;
}
}
private static DBComponent GetDBComponent(this LocationComponent self)
{
Scene root = self.Root();
DBManagerComponent dbManagerComponent = root.GetComponent<DBManagerComponent>();
if (dbManagerComponent == null)
{
throw new Exception($"location db manager not found scene: {root.Name}");
}
return dbManagerComponent.GetZoneDB(root.Fiber.Zone);
}
private static async ETTask SaveInfoToDB(this LocationComponent self, LocationInfo locationInfo)
{
if (locationInfo == null)
{
return;
}
long key = locationInfo.Id;
EntityRef<LocationComponent> selfRef = self;
EntityRef<LocationInfo> locationInfoRef = locationInfo;
DBComponent dbComponent = self.GetDBComponent();
EntityRef<DBComponent> dbComponentRef = dbComponent;
Scene root = self.Root();View on GitHub (pinned to 5cab01f7a8)
Solutions
- Ensure the provider scene for that sceneType is started and its registration reached this proxy before consumers call (check OnServiceChangeAddService logs for the sceneName).
- Verify the sceneType integer resolves to the same SceneType name on both registration and query via SceneTypeSingleton.Instance.GetSceneName(sceneType).
- Raise ServiceResolveRetryTimes / ServiceResolveRetryIntervalMs on the proxy so transient registration races resolve during the built-in retry loop.
- Pre-check with GetBySceneType(sceneType) and fall back / queue the request when Count == 0 instead of relying on the exception.
Example fix
// before
ActorId actorId = self.ResolveServiceActorIdByRouteKeyOnce(sceneType, sceneTypeName, routeKey);
// after
List<ServiceInfo> services = self.GetBySceneType(sceneType);
if (services == null || services.Count == 0)
{
// defer or fail soft instead of letting routing throw
return default;
}
ActorId actorId = self.ResolveServiceActorIdByRouteKeyOnce(sceneType, sceneTypeName, routeKey); Defensive patterns
Strategy: retry
Validate before calling
List<ServiceInfo> services = proxy.GetBySceneType(sceneType);
if (services == null || services.Count == 0)
{
// provider not registered yet; defer or fall back
return;
} Try / catch
try
{
T resp = await proxy.CallBySceneTypeAsync<T>(sceneType, request, nameof(request), routeKey);
}
catch (RpcException ex) when (ex.Error == ErrorCode.ERR_ServiceNotFound)
{
// exhaustive retries already attempted by the proxy; surface as service unavailable
Log.Warning($"service not found for sceneType {sceneType}: {ex.Message}");
} Prevention
- Register provider scenes before starting consumers, and gate consumer start on an OnServiceChangeAddService event for the required sceneType.
- Tune ServiceResolveRetryTimes / ServiceResolveRetryIntervalMs to outlast normal startup races.
- Always pass the sceneType via the shared SceneType enum so SceneTypeSingleton.GetSceneName resolves identically on both sides.
When it happens
Trigger: Calling CallBySceneTypeAsync / ResolveServiceActorIdByRouteKeyOnce when no service of the target sceneType has registered with the ServiceDiscoveryProxy local cache (GetBySceneType returns 0 entries), or when every instance deregistered before the call resolved. ResolveServiceActorIdByRouteKeyOnce already guards Count==0 at line 408, so reaching line 433 means a concurrent mutation emptied the list between the check and SelectServiceActorIdByRouteKey.
Common situations: Target provider scene not started yet; service registered under a different sceneType metadata key than the query (SceneTypeSingleton.GetSceneName mismatch); startup race where the consumer calls before the provider registers; wrong zone filter narrowing the result to zero.
Related errors
- ERR_LocationAlreadyLocked
- location add failed key: {key} actorId: {actorId} error: {re
- location lock failed key: {key} actorId: {actorId} error: {r
- location unlock failed key: {key} oldActorId: {oldActorId} n
- location remove failed key: {key} expectedActorId: {expected
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/f80a24b72dd74f2f.
Report an issue: GitHub.