egametang/ET · error · RpcException
location lock failed key: {key} actorId: {actorId} error: {r
Error message
location lock failed key: {key} actorId: {actorId} error: {response.Message} What it means
Thrown by LocationProxyComponent.LockWithToken when the RPC response from the primary Location scene returns a non-success error code. This wraps the server-side error with proxy-level context. The most common underlying cause is ERR_LocationAlreadyLocked (another actor holds the lock) or ERR_LocationLockOwnerMismatch (a different actor owns the route entry).
Source
Thrown at Packages/cn.etetet.actorlocation/Scripts/Hotfix/Server/LocationProxyComponentSystem.cs:235
$"location add failed key: {key} actorId: {actorId} error: {response.Message}");
}
}
public static async ETTask<long> LockWithToken(this LocationProxyComponent self, int type, long key, ActorId actorId,
int time = 60000)
{
Log.Info($"location proxy lock {key}, {actorId} {self.GetSingleton<TimeInfo>().ServerNow()}");
ObjectLockRequest request = ObjectLockRequest.Create();
request.Type = type;
request.Key = key;
request.ActorId = actorId;
request.Time = time;
ObjectLockResponse response = (ObjectLockResponse)await self.CallPrimaryWithRetry(key, request);
if (response.Error != ErrorCode.ERR_Success)
{
throw new RpcException(response.Error,
$"location lock failed key: {key} actorId: {actorId} error: {response.Message}");
}
return response.LockToken;
}
[Obsolete("Use LockWithToken and pass the returned token to UnLock.", true)]
public static async ETTask Lock(this LocationProxyComponent self, int type, long key, ActorId actorId,
int time = 60000)
{
await self.LockWithToken(type, key, actorId, time);
}
[Obsolete("Use UnLock overload with lockToken.", true)]
public static ETTask UnLock(this LocationProxyComponent self, int type, long key, ActorId oldActorId,
ActorId newActorId)
{
throw new RpcException(ErrorCode.ERR_LocationLockTokenMismatch,View on GitHub (pinned to 5cab01f7a8)
Solutions
- Catch RpcException and inspect e.Error: ERR_LocationAlreadyLocked requires waiting for the lock to release or expire before retrying.
- For ERR_LocationLockOwnerMismatch, ensure the actorId matches the current route owner before locking.
- Implement a retry loop with backoff at the application level for transient lock conflicts.
- For ERR_LocationPrimaryUnavailable after exhaustion, verify Location scene topology.
Example fix
// before -- unhandled lock
long token = await locationProxy.LockWithToken(type, key, actorId, 60000);
// after -- retry on lock conflict with backoff
long token = 0;
for (int i = 0; i < maxRetries; i++)
{
try
{
token = await locationProxy.LockWithToken(type, key, actorId, 60000);
break;
}
catch (RpcException e) when (e.Error == ErrorCode.ERR_LocationAlreadyLocked && i < maxRetries - 1)
{
await root.TimerComponent.WaitAsync(100 * (i + 1));
}
} Defensive patterns
Strategy: try-catch
Try / catch
try
{
token = await locationProxy.LockWithToken(type, key, actorId, 60000);
}
catch (RpcException e) when (e.Error == ErrorCode.ERR_LocationAlreadyLocked)
{
// Retry with backoff or fail gracefully
Log.Warning($"Lock conflict on key {key}: {e.Message}");
}
catch (RpcException e) when (e.Error == ErrorCode.ERR_LocationLockOwnerMismatch)
{
Log.Warning($"Lock owner mismatch on key {key}: {e.Message}");
} Prevention
- Catch RpcException from LockWithToken and handle by error code -- AlreadyLocked and OwnerMismatch are the most common.
- For contention scenarios, implement a bounded retry loop with backoff at the application level.
- Always store the returned token and pass it to the matching UnLock.
When it happens
Trigger: LocationProxyComponent.LockWithToken(type, key, actorId, time) calls CallPrimaryWithRetry, gets response.Error != ERR_Success. LockWithToken does NOT internally retry on ERR_LocationAlreadyLocked (that is not in the retry-eligible set), so a lock conflict surfaces immediately as this exception.
Common situations: Another actor already holds the lock (ERR_LocationAlreadyLocked); the route entry is owned by a different actor (ERR_LocationLockOwnerMismatch); primary was unavailable after all retries (ERR_LocationPrimaryUnavailable).
Related errors
- location add failed key: {key} actorId: {actorId} error: {re
- ERR_LocationGetRetry
- location remove failed key: {key} expectedActorId: {expected
- location get failed key: {key} error: {response.Error} messa
- service discovery agent response error, request: {requestNam
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/92f66b0505ded054.
Report an issue: GitHub.