{"record":{"id":"660d815d2e817f6f","repo":"EllanJiang/GameFramework","slug":"updatable-version-list-has-been-parsed","errorCode":null,"errorMessage":"Updatable version list has been parsed.","messagePattern":"Updatable version list has been parsed\\.","errorType":"exception","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/Resource/ResourceManager.ResourceChecker.cs","lineNumber":259,"sourceCode":"                        m_ResourceManager.m_FileSystemManager.DestroyFileSystem(fileSystem.Value, true);\n                        removedFileSystemNames.Add(fileSystem.Key);\n                    }\n                }\n\n                if (removedFileSystemNames != null)\n                {\n                    foreach (string removedFileSystemName in removedFileSystemNames)\n                    {\n                        m_ResourceManager.m_ReadWriteFileSystems.Remove(removedFileSystemName);\n                    }\n                }\n            }\n\n            private void OnLoadUpdatableVersionListSuccess(string fileUri, byte[] bytes, float duration, object userData)\n            {\n                if (m_UpdatableVersionListReady)\n                {\n                    throw new GameFrameworkException(\"Updatable version list has been parsed.\");\n                }\n\n                MemoryStream memoryStream = null;\n                try\n                {\n                    memoryStream = new MemoryStream(bytes, false);\n                    UpdatableVersionList versionList = m_ResourceManager.m_UpdatableVersionListSerializer.Deserialize(memoryStream);\n                    if (!versionList.IsValid)\n                    {\n                        throw new GameFrameworkException(\"Deserialize updatable version list failure.\");\n                    }\n\n                    UpdatableVersionList.Asset[] assets = versionList.GetAssets();\n                    UpdatableVersionList.Resource[] resources = versionList.GetResources();\n                    UpdatableVersionList.FileSystem[] fileSystems = versionList.GetFileSystems();\n                    UpdatableVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups();\n                    m_ResourceManager.m_ApplicableGameVersion = versionList.ApplicableGameVersion;\n                    m_ResourceManager.m_InternalResourceVersion = versionList.InternalResourceVersion;","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/Resource/ResourceManager.ResourceChecker.cs#L241-L277","documentation":"OnLoadUpdatableVersionListSuccess guards against parsing the remote (updatable) version list twice: if m_UpdatableVersionListReady is already true when the load-success callback fires, it throws this GameFrameworkException. This protects the check pipeline from duplicate callbacks (e.g. CheckResources called twice while a load is still pending).","triggerScenarios":"Calling CheckResources twice in quick succession so the first parse completes (sets m_UpdatableVersionListReady=true) and a second LoadBytes callback for the same list arrives afterwards.","commonSituations":"UI double-click triggering resource update twice; two scripts both calling CheckResources on startup; a custom ResourceHelper that invokes both success callbacks or re-invokes the same one.","solutions":["Guard your UI/logic so CheckResources is only called once per session (disable the button while updating).","Track an isChecking flag and skip subsequent CheckResources calls until ResourceCheckComplete fires.","Fix a custom ResourceHelper that fires the success callback more than once."],"exampleFix":"// before\npublic void OnUpdateButtonClicked() { m_ResourceComponent.CheckResources(); } // can double-fire\n\n// after\nprivate bool m_Checking;\npublic void OnUpdateButtonClicked()\n{\n    if (m_Checking) return;\n    m_Checking = true;\n    m_ResourceComponent.CheckResources();\n}","handlingStrategy":"type-guard","validationCode":"private bool m_CheckInProgress;\nvoid SafeCheck()\n{\n    if (m_CheckInProgress) return;\n    m_CheckInProgress = true;\n    m_ResourceComponent.ResourceCheckComplete += (…) => m_CheckInProgress = false;\n    m_ResourceComponent.CheckResources();\n}","typeGuard":"bool CanStartResourceCheck => !m_CheckInProgress;","tryCatchPattern":"try { m_ResourceComponent.CheckResources(); }\ncatch (GameFrameworkException ex) when (ex.Message.Contains(\"has been parsed\"))\n{\n    Debug.LogWarning(\"Resource check already running; ignoring duplicate call.\");\n}","preventionTips":["Debounce the update button and guard with an is-checking flag.","Ensure only one code path ever calls CheckResources per session.","If using a custom ResourceHelper, guarantee each LoadBytes completes exactly one callback."],"tags":["gameframework","resource","duplicate-callback","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"d0c010b05167c58e92350449d04864a91ca13fd2","analyzedAt":"2026-09-15T13:37:15.352Z","contentChangedAt":"2026-09-15T13:37:15.352Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}