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.

Solutions

  1. Use LocationProxyComponent.Get which automatically retries on ERR_LocationGetRetry up to 20 times (configurable via locationRequestRetryTimes) with increasing delay.
  2. If retries are exhausted, increase locationRequestRetryTimes or locationRequestRetryIntervalMs on the LocationProxyComponent.
  3. Ensure locks are released promptly -- check for leaked locks from crashed processes.
  4. 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

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


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/ea7ad6de2b4e253c. Report an issue: GitHub.

Appendix: 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)