egametang/ET · error · RpcException
ERR_LocationLockTokenMismatch
ERR_LocationLockTokenMismatch
Error message
location unlock requires lock token key: {key} oldActorId: {oldActorId} newActorId: {newActorId} What it means
Thrown by the obsolete UnLock overload that lacks a lockToken parameter. The location-lock API was migrated to a token-based scheme: LockWithToken returns a long token that must be passed to UnLock. The [Obsolete(..., true)] attribute makes the C# compiler reject any call at compile time (error CS0619); this runtime throw exists as a safety net for reflection-based or dynamically dispatched calls that bypass the compiler check.
Source
Thrown at Packages/cn.etetet.actorlocation/Scripts/Hotfix/Server/LocationProxyComponentSystem.cs:253
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,
$"location unlock requires lock token key: {key} oldActorId: {oldActorId} newActorId: {newActorId}");
}
public static async ETTask UnLock(this LocationProxyComponent self, int type, long key, ActorId oldActorId,
ActorId newActorId, long lockToken)
{
Log.Info(
$"location proxy unlock {key}, {newActorId} lockToken: {lockToken} {self.GetSingleton<TimeInfo>().ServerNow()}");
ObjectUnLockRequest request = ObjectUnLockRequest.Create();
request.Type = type;
request.Key = key;
request.OldActorId = oldActorId;
request.NewActorId = newActorId;
request.LockToken = lockToken;
ObjectUnLockResponse response = (ObjectUnLockResponse)await self.CallPrimaryWithRetry(key, request);
if (response.Error != ErrorCode.ERR_Success)View on GitHub (pinned to 5cab01f7a8)
Solutions
- Replace Lock(...) with LockWithToken(type, key, actorId, time) and capture the returned long lockToken.
- Replace the 4-parameter UnLock(...) call with the 5-parameter UnLock(type, key, oldActorId, newActorId, lockToken) overload, passing the captured token.
- Remove any #pragma warning disable CS0619 / CS0618 directives around lock/unlock code so the compiler catches the obsolete overload.
- If invoking via reflection, update the MethodInfo lookup to select the 5-parameter overload.
Example fix
// before locationProxy.Lock(type, key, actorId); // ... later ... locationProxy.UnLock(type, key, oldActorId, newActorId); // CS0619 or runtime throw // after long lockToken = await locationProxy.LockWithToken(type, key, actorId); // ... later ... await locationProxy.UnLock(type, key, oldActorId, newActorId, lockToken);
Defensive patterns
Strategy: validation
Validate before calling
// Ensure you use the token-based API exclusively.
// The compiler enforces this via [Obsolete(..., true)] = CS0619.
// If using reflection, explicitly select the 5-parameter overload:
var method = typeof(LocationProxyComponentSystem)
.GetMethods()
.First(m => m.Name == "UnLock" && m.GetParameters().Length == 6); // self + 5 params incl. lockToken
// Verify lockToken is non-zero before unlocking:
if (lockToken == 0)
{
throw new InvalidOperationException("lockToken must come from LockWithToken");
} Prevention
- Always pair LockWithToken → UnLock(5-param, lockToken). Never call the 4-param UnLock.
- Do not suppress CS0619 around lock/unlock code.
- Store the lockToken in a field or pass it through the call chain; never discard it.
- The token is the only proof of lock ownership — treat it like a capability.
When it happens
Trigger: Invoking UnLock(type, key, oldActorId, newActorId) — the 4-parameter overload without lockToken — via reflection (MethodInfo.Invoke), dynamic dispatch, or a build that suppresses CS0619. Under normal compilation this method is unreachable.
Common situations: Upgrading from a pre-token version of cn.etetet.actorlocation where UnLock did not require a token. Test harnesses or serialization frameworks that invoke methods by signature via reflection. Code that uses #pragma warning disable CS0619 around unlock calls.
Related errors
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/f0368f24f3c481c9.
Report an issue: GitHub.