egametang/ET · error · RpcException
ERR_NotFoundActor
ERR_NotFoundActor
Error message
{message} What it means
In SendInner, the location lookup completed and returned default(ActorId) — the entity has no registered location. The sender is explicitly removed (self.Remove(entityId)) and ERR_NotFoundActor is thrown. Unlike the timeout errors, this is a definitive 'entity does not exist in location' result, not a transient disposal.
Source
Thrown at Packages/cn.etetet.actorlocation/Scripts/Hotfix/Server/MessageLocationSenderComponentSystem.cs:134
throw new RpcException(ErrorCode.ERR_MessageTimeout, $"{message}");
}
if (messageLocationSender.ActorId == default)
{
root = rootRef;
self = selfRef;
ActorId actorId = await root.GetComponent<LocationProxyComponent>().Get((int)self.Id, messageLocationSender.Id);
messageLocationSender = messageLocationSenderRef;
if (messageLocationSender == null)
{
throw new RpcException(ErrorCode.ERR_ActorLocationSenderTimeout2, $"{message}");
}
if (actorId == default)
{
self = selfRef;
self?.Remove(entityId);
throw new RpcException(ErrorCode.ERR_NotFoundActor, $"{message}");
}
messageLocationSender.ActorId = actorId;
}
messageLocationSender = messageLocationSenderRef;
messageLocationSender.LastSendOrRecvTime = messageLocationSender.GetSingleton<TimeInfo>().ServerNow();
root = rootRef;
root.GetComponent<MessageSender>().Send(messageLocationSender.ActorId, message);
}
}
// 发给不会改变位置的actorlocation用这个,这种actor消息不会阻塞发送队列,性能更高,发送过去找不到actor不会重试
// 发送过去找不到actor不会重试,用此方法,你得保证actor提前注册好了location
public static async ETTask<IResponse> Call(this MessageLocationSenderOneType self, long entityId, IRequest request)
{
MessageLocationSender messageLocationSender = self.GetOrCreate(entityId);
EntityRef<MessageLocationSender> messageLocationSenderRef = messageLocationSender;View on GitHub (pinned to 5cab01f7a8)
Solutions
- Ensure the target entity registered its location via AddLocation(type) before any sends are attempted.
- Verify the entityId is correct and the target entity still exists.
- Catch RpcException with ERR_NotFoundActor and handle gracefully (drop the message, log a warning, or notify the sender).
- Use the non-location MessageSender for actors that don't migrate, or guarantee registration ordering.
Defensive patterns
Strategy: validation
Validate before calling
// Before sending, verify the entity has a registered location:
ActorId actorId = await root.GetComponent<LocationProxyComponent>().Get(type, entityId);
if (actorId == default)
{
Log.Warning($"entity {entityId} has no location, skipping send");
return;
}
// Now send safely
senderOneType.Send(entityId, message); Try / catch
try
{
await senderOneType.SendAsync(entityId, message);
}
catch (RpcException e) when (e.Error == ErrorCode.ERR_NotFoundActor)
{
Log.Warning($"entity {entityId} not found in location, cannot send");
// drop message or notify caller
} Prevention
- Ensure entities register their location via AddLocation(type) before any sends.
- Verify entityId correctness at the call site.
- Don't send to entities that may have been destroyed — check lifecycle first.
- For non-migrating actors, consider using MessageSender directly instead of MessageLocationSender.
When it happens
Trigger: MessageLocationSenderOneType.Send(entityId, message) where entityId was never registered via Add/AddLocation, or whose location was already removed via Remove.
Common situations: Sending to an entity before it has registered its location (ordering bug). Sending to an entity after it was destroyed and its location cleaned up. Wrong entityId passed by the caller. Race between entity destruction and a pending send.
Related errors
- ERR_LocationGetRetry
- ERR_LocationPrimaryUnavailable
- ERR_LocationPrimaryUnavailable
- location primary actor id is empty: {primarySceneName}
- location proxy message sender is null: {self.Root().Name}
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/7414ef20ce901aa6.
Report an issue: GitHub.