{"record":{"id":"5d9362745569d0e8","repo":"egametang/ET","slug":"err-locationlocktokenmismatch","errorCode":"ERR_LocationLockTokenMismatch","errorMessage":"location unlock token mismatch type: {locationType} key: {key} oldActorId: {oldActorId} requestToken: {lockToken} holdToken: {state.LockToken}","messagePattern":"location unlock token mismatch type: (.+?) key: (.+?) oldActorId: (.+?) requestToken: (.+?) holdToken: (.+?)","errorType":"exception","errorClass":"RpcException","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.actorlocation/Scripts/Hotfix/Server/LocationComponentSystem.cs","lineNumber":518,"sourceCode":"                            self.RestoreStates(key, snapshot);\n                        }\n\n                        throw;\n                    }\n\n                    throw new RpcException(ErrorCode.ERR_LocationLockNotFound,\n                        $\"location unlock expired type: {locationType} key: {key} oldActorId: {oldActorId}\");\n                }\n\n                if (!IsLocked(state))\n                {\n                    throw new RpcException(ErrorCode.ERR_LocationLockNotFound,\n                        $\"location unlock not found type: {locationType} key: {key} oldActorId: {oldActorId}\");\n                }\n\n                if (lockToken == 0 || state.LockToken != lockToken)\n                {\n                    throw new RpcException(ErrorCode.ERR_LocationLockTokenMismatch,\n                        $\"location unlock token mismatch type: {locationType} key: {key} oldActorId: {oldActorId} requestToken: {lockToken} holdToken: {state.LockToken}\");\n                }\n\n                if (oldActorId != state.ActorId)\n                {\n                    throw new RpcException(ErrorCode.ERR_LocationLockOwnerMismatch,\n                        $\"location unlock old actor mismatch type: {locationType} key: {key} requestOldActorId: {oldActorId} holdActorId: {state.ActorId}\");\n                }\n\n                Log.Info(\n                    $\"location unlock type: {locationType} key: {key} actorId: {oldActorId} newActorId: {newActorId} lockToken: {lockToken}\");\n\n                state.ActorId = newActorId;\n                state.LockToken = default;\n                state.LockExpireTime = default;\n                locationInfo.TypeStates[locationType] = state;\n\n                try","sourceCodeStart":500,"sourceCodeEnd":536,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.actorlocation/Scripts/Hotfix/Server/LocationComponentSystem.cs#L500-L536","documentation":"GetOneBySceneType throws when the count of StartSceneConfig entries matching a (zone, sceneType) pair is not exactly 1 — i.e. zero or two-or-more. It is the singleton-lookup invariant for callers that expect exactly one scene of a given type per zone, built on top of GetBySceneType which filters by Zone and SceneType name.","triggerScenarios":"Calling GetOneBySceneType(zone, sceneType) when the StartSceneConfig table has no entry for that zone+sceneType (count 0), or has duplicate/ambiguous entries (count >= 2). SceneType is resolved through SceneTypeSingleton.Instance.GetSceneName, so an unknown enum also yields count 0.","commonSituations":"StartSceneConfig table missing the scene for that zone; duplicate rows for the same zone+sceneType; wrong zone id passed by the caller; sceneType integer does not map to the expected name via SceneTypeSingleton.","solutions":["Inspect the StartSceneConfig table for the given zone+sceneType and ensure exactly one entry exists.","Remove duplicates or add the missing scene definition, then reload configs.","Verify the zone and sceneType values passed are correct (check SceneTypeSingleton.GetSceneName mapping).","If multiple scenes are legitimately valid, switch the caller to GetBySceneType and select explicitly instead of GetOneBySceneType."],"exampleFix":"// before\nStartSceneConfig config = category.GetOneBySceneType(zone, sceneType);\n\n// after\nList<StartSceneConfig> configs = category.GetBySceneType(zone, sceneType);\nif (configs.Count != 1)\n{\n    Log.Error($\"expected exactly 1 scene for zone {zone} sceneType {sceneType}, got {configs.Count}\");\n    return null;\n}\nStartSceneConfig config = configs[0];","handlingStrategy":"validation","validationCode":"List<StartSceneConfig> configs = category.GetBySceneType(zone, sceneType);\nif (configs.Count != 1)\n{\n    Log.Error($\"expected 1 scene for zone {zone} sceneType {sceneType}, found {configs.Count}\");\n    return null;\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    StartSceneConfig cfg = category.GetOneBySceneType(zone, sceneType);\n}\ncatch (Exception ex) when (ex.Message.Contains(\"scene config count is not one\"))\n{\n    Log.Error($\"ambiguous/missing scene config: {ex.Message}\");\n}","preventionTips":["Keep exactly one StartSceneConfig per zone+sceneType for singleton-looked-up scene types.","Validate zone and sceneType against SceneTypeSingleton before calling GetOneBySceneType.","Use GetBySceneType when multiple scenes are legitimately valid, and select explicitly."],"tags":["startconfig","scene-config","config","zone","singleton-lookup"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}