{"record":{"id":"9cd289521270b48f","repo":"EllanJiang/GameFramework","slug":"read-only-version-list-has-been-parsed","errorCode":null,"errorMessage":"Read-only version list has been parsed.","messagePattern":"Read-only version list has been parsed\\.","errorType":"exception","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/Resource/ResourceManager.ResourceChecker.cs","lineNumber":372,"sourceCode":"                {\n                    if (memoryStream != null)\n                    {\n                        memoryStream.Dispose();\n                        memoryStream = null;\n                    }\n                }\n            }\n\n            private void OnLoadUpdatableVersionListFailure(string fileUri, string errorMessage, object userData)\n            {\n                throw new GameFrameworkException(Utility.Text.Format(\"Updatable version list '{0}' is invalid, error message is '{1}'.\", fileUri, string.IsNullOrEmpty(errorMessage) ? \"<Empty>\" : errorMessage));\n            }\n\n            private void OnLoadReadOnlyVersionListSuccess(string fileUri, byte[] bytes, float duration, object userData)\n            {\n                if (m_ReadOnlyVersionListReady)\n                {\n                    throw new GameFrameworkException(\"Read-only version list has been parsed.\");\n                }\n\n                MemoryStream memoryStream = null;\n                try\n                {\n                    memoryStream = new MemoryStream(bytes, false);\n                    LocalVersionList versionList = m_ResourceManager.m_ReadOnlyVersionListSerializer.Deserialize(memoryStream);\n                    if (!versionList.IsValid)\n                    {\n                        throw new GameFrameworkException(\"Deserialize read-only version list failure.\");\n                    }\n\n                    LocalVersionList.Resource[] resources = versionList.GetResources();\n                    LocalVersionList.FileSystem[] fileSystems = versionList.GetFileSystems();\n\n                    foreach (LocalVersionList.FileSystem fileSystem in fileSystems)\n                    {\n                        int[] resourceIndexes = fileSystem.GetResourceIndexes();","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/Resource/ResourceManager.ResourceChecker.cs#L354-L390","documentation":"GameFramework's ResourceChecker throws this when the read-only version list load-success callback fires but m_ReadOnlyVersionListReady is already true, meaning the version list was already parsed. It guards against the async resource-loading pipeline invoking the success handler twice (e.g. duplicate events or a re-entrant check), which would corrupt check state by parsing the list a second time.","triggerScenarios":"OnLoadReadOnlyVersionListSuccess is invoked a second time after the version list has already been successfully parsed (m_ReadOnlyVersionListReady == true). Typically caused by duplicate load-success events from the resource helper or starting a new check without resetting the checker.","commonSituations":"Subscribing the same callback to two load tasks; a custom resource load helper that fires success more than once for one request; re-running CheckResources on a checker whose ready flags were never reset.","solutions":["Ensure the read-only version list load task fires its success callback exactly once per request","Verify your IResourceHelper/LoadBytes implementation does not invoke both success and retry-success paths","Reset the ResourceChecker state (or recreate it) before starting a new resource check","Check for duplicate event subscriptions to the resource manager's load events"],"exampleFix":"// before: helper may invoke onSuccess twice\nhelper.LoadBytes(uri, onSuccess, onFailure);\n// after: guard with a local latch in the helper\nbool completed = false;\nvoid OnLoaded(byte[] bytes) { if (completed) return; completed = true; onSuccess(bytes); }","handlingStrategy":"try-catch","validationCode":"if (checker == null) throw new InvalidOperationException(\"Checker not initialized\");","typeGuard":null,"tryCatchPattern":"try { checker.CheckResources(); }\ncatch (GameFrameworkException ex) when (ex.Message.Contains(\"has been parsed\")) { Log.Warning(\"Duplicate version list event ignored\"); }","preventionTips":["Fire exactly one success/failure callback per load request in custom helpers","Never re-run resource checks on a checker instance that already completed without resetting it","Deduplicate event handler subscriptions","Add logging in the load helper to detect double completion"],"tags":["gameframework","resource","version-list","duplicate-callback"],"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"}