egametang/ET · error · RpcException
ERR_LocationLockNotFound
ERR_LocationLockNotFound
Error message
location unlock not found type: {locationType} key: {key} oldActorId: {oldActorId} What it means
TargetSelectHandler<Node>.Handle throws when the TargetSelector node passed in is not assignable to the handler's generic Node type. The dispatcher registers handlers keyed by node Type and, on dispatch, walks node.GetType() up through BaseType to find a match, so a correct registration should never deliver a mismatched node to a handler.
Source
Thrown at Packages/cn.etetet.actorlocation/Scripts/Hotfix/Server/LocationComponentSystem.cs:480
}
public static async ETTask UnLock(this LocationComponent self, int locationType, long key, ActorId oldActorId, ActorId newActorId,
long lockToken)
{
EntityRef<LocationComponent> selfRef = self;
using (await self.Root().CoroutineLockComponent.Wait(CoroutineLockType.Location, key))
{
self = selfRef;
if (self == null)
{
return;
}
LocationInfo locationInfo = await self.GetOrLoadInfo(key);
self = selfRef;
if (self == null || locationInfo == null || !TryGetRouteState(locationInfo, locationType, out LocationTypeState state))
{
throw new RpcException(ErrorCode.ERR_LocationLockNotFound,
$"location unlock not found type: {locationType} key: {key} oldActorId: {oldActorId}");
}
Dictionary<int, LocationTypeState> snapshot = CreateStatesSnapshot(locationInfo);
if (self.IsExpiredLock(state))
{
state.LockToken = default;
state.LockExpireTime = default;
locationInfo.TypeStates[locationType] = state;
try
{
await self.SaveInfoToDB(locationInfo);
}
catch
{
self = selfRef;
if (self != null)View on GitHub (pinned to 5cab01f7a8)
Solutions
- Ensure each TargetSelector subtype has exactly one handler whose generic Node type equals (or is a base of) the node type it should receive.
- Confirm GetNodeType() returns typeof(Node) and that this matches the key used in Register (handlers.TryAdd(nodeType, ...)).
- Check for duplicate or conflicting registrations across the TargetSelector hierarchy in the handlers dictionary.
- Add a dedicated handler for the specific node subtype that is currently mismatching.
Example fix
// before
public async ETTask<int> Handle(TargetSelector node, ...)
{
if (node is not Node c)
{
throw new Exception($"type mismatch: {node.GetType().FullName} to {typeof(Node).Name}");
}
return await this.Run(c, unit, spellConfig);
}
// after
public async ETTask<int> Handle(TargetSelector node, ...)
{
if (node is not Node c)
{
Log.Error($"node type mismatch: {node.GetType().FullName} expected {typeof(Node).Name}; returning 0");
return 0;
}
return await this.Run(c, unit, spellConfig);
} Defensive patterns
Strategy: type-guard
Type guard
static bool IsHandlerFor(ITargetSelectHandler handler, TargetSelector node)
{
return handler.GetNodeType().IsAssignableFrom(node.GetType());
} Try / catch
try
{
return await handler.Handle(node, unit, spellConfig);
}
catch (Exception ex) when (ex.Message.Contains("type mismatch"))
{
Log.Error($"node/handler type mismatch: {node.GetType().FullName} vs {handler.GetNodeType().Name}");
return 0;
} Prevention
- Register exactly one handler per TargetSelector type, keyed by GetNodeType(), to keep dispatch unambiguous.
- Keep GetNodeType() returning typeof(Node) consistent with the generic constraint on every handler.
- Add a handler for each new TargetSelector subclass instead of relying on a base-type match.
When it happens
Trigger: A handler's Handle is invoked with a node whose runtime type is not the registered Node type — happens only if the handlers dictionary was populated for the wrong key, GetNodeType() returns a type inconsistent with the generic constraint, or a node subclass has no dedicated handler and the BaseType walk landed on a handler registered for a sibling type.
Common situations: Two handlers registered under keys in the same inheritance chain causing an ambiguous/incorrect lookup; a TargetSelector subclass added without a matching handler; handler generic Node parameter changed during refactor but GetNodeType unchanged.
Related errors
- bt handler not inherit IMActorHandler abstract class: {obj.G
- bt node is null
- not found bt handler: {node.GetType().FullName}
- ERR_LocationLockOwnerMismatch
- 不能把{value.GetType()}转换为{typeof (T)}
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/e9a7f00906470bd0.
Report an issue: GitHub.