egametang/ET · warning · RpcException
ERR_LocationGetRetry
ERR_LocationGetRetry
Error message
location get retry type: {locationType} key: {key} actorId: {state.ActorId} lockToken: {state.LockToken} What it means
Thrown by LocationComponent.Get when the requested key/type is currently locked (LockToken != 0) and the lock has not expired. Get refuses to return the actorId of a locked entry because the entry is in a transitional state -- the lock holder may be migrating or replacing the actor. The caller is expected to retry after the lock is released or expires.
Source
Thrown at Packages/cn.etetet.actorlocation/Scripts/Hotfix/Server/LocationComponentSystem.cs:600
try
{
await self.SaveInfoToDB(locationInfo);
}
catch
{
self = selfRef;
if (self != null)
{
self.RestoreStates(key, snapshot);
}
throw;
}
}
else if (IsLocked(state))
{
throw new RpcException(ErrorCode.ERR_LocationGetRetry,
$"location get retry type: {locationType} key: {key} actorId: {state.ActorId} lockToken: {state.LockToken}");
}
Log.Info($"location get type: {locationType} key: {key} actorId: {state.ActorId}");
return state.ActorId;
}
}
public static void RefreshPrimaryState(this LocationComponent self)
{
Scene root = self.Root();
if (root == null)
{
return;
}
ServiceDiscoveryProxy serviceDiscoveryProxy = root.GetComponent<ServiceDiscoveryProxy>();
if (serviceDiscoveryProxy == null)View on GitHub (pinned to 5cab01f7a8)
Solutions
- Use LocationProxyComponent.Get which automatically retries on ERR_LocationGetRetry up to 20 times (configurable via locationRequestRetryTimes) with increasing delay.
- If retries are exhausted, increase locationRequestRetryTimes or locationRequestRetryIntervalMs on the LocationProxyComponent.
- Ensure locks are released promptly -- check for leaked locks from crashed processes.
- If using time=0 locks, switch to finite-time locks so they auto-expire and unblock Get.
Example fix
// before -- direct Get on LocationComponent, no retry ActorId id = await locationComponent.Get(type, key); // after -- proxy Get with built-in retry ActorId id = await locationProxy.Get(type, key);
Defensive patterns
Strategy: retry
Try / catch
// LocationProxyComponent.Get already retries ERR_LocationGetRetry internally.
// If you call LocationComponent.Get directly, wrap with retry:
for (int i = 0; i < maxRetries; i++)
{
try { return await locationComponent.Get(type, key); }
catch (RpcException e) when (e.Error == ErrorCode.ERR_LocationGetRetry && i < maxRetries - 1)
{
await root.TimerComponent.WaitAsync(100 * (i + 1));
}
} Prevention
- Always use LocationProxyComponent.Get instead of LocationComponent.Get -- it has built-in retry logic.
- Keep locks short-lived to minimize Get contention.
- Tune locationRequestRetryTimes and locationRequestRetryIntervalMs based on expected lock duration.
When it happens
Trigger: Calling LocationComponent.Get(locationType, key) when TryGetRouteState returns a state with LockToken != 0 and IsExpiredLock is false (either LockExpireTime==0 for a permanent lock, or ServerNow() < LockExpireTime). The proxy-level Get catches ERR_LocationGetRetry and retries up to locationRequestRetryTimes with exponential backoff.
Common situations: An actor is being migrated (locked during migration) and another service tries to look it up; a long-running operation holds a lock with a large TTL; lock was acquired with time=0 (no expiry) and never released.
Related errors
- location lock failed key: {key} actorId: {actorId} error: {r
- location get retry exceeded key: {key} retry: {retryCount}/{
- ERR_LocationPrimaryUnavailable
- ERR_LocationPrimaryUnavailable
- location primary actor id is empty: {primarySceneName}
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/ea7ad6de2b4e253c.
Report an issue: GitHub.