{"record":{"id":"cbebab91ff1e00f2","repo":"EllanJiang/GameFramework","slug":"read-only-path-is-invalid","errorCode":null,"errorMessage":"Read-only path is invalid.","messagePattern":"Read-only path is invalid\\.","errorType":"validation","errorClass":"GameFrameworkException","httpStatus":null,"severity":"critical","filePath":"GameFramework/Resource/ResourceManager.ResourceChecker.cs","lineNumber":73,"sourceCode":"            {\n                m_CheckInfos.Clear();\n            }\n\n            /// <summary>\n            /// 检查资源。\n            /// </summary>\n            /// <param name=\"currentVariant\">当前使用的变体。</param>\n            /// <param name=\"ignoreOtherVariant\">是否忽略处理其它变体的资源，若不忽略，将会移除其它变体的资源。</param>\n            public void CheckResources(string currentVariant, bool ignoreOtherVariant)\n            {\n                if (m_ResourceManager.m_ResourceHelper == null)\n                {\n                    throw new GameFrameworkException(\"Resource helper is invalid.\");\n                }\n\n                if (string.IsNullOrEmpty(m_ResourceManager.m_ReadOnlyPath))\n                {\n                    throw new GameFrameworkException(\"Read-only path is invalid.\");\n                }\n\n                if (string.IsNullOrEmpty(m_ResourceManager.m_ReadWritePath))\n                {\n                    throw new GameFrameworkException(\"Read-write path is invalid.\");\n                }\n\n                m_CurrentVariant = currentVariant;\n                m_IgnoreOtherVariant = ignoreOtherVariant;\n                m_ResourceManager.m_ResourceHelper.LoadBytes(Utility.Path.GetRemotePath(Path.Combine(m_ResourceManager.m_ReadWritePath, RemoteVersionListFileName)), new LoadBytesCallbacks(OnLoadUpdatableVersionListSuccess, OnLoadUpdatableVersionListFailure), null);\n                m_ResourceManager.m_ResourceHelper.LoadBytes(Utility.Path.GetRemotePath(Path.Combine(m_ResourceManager.m_ReadOnlyPath, LocalVersionListFileName)), new LoadBytesCallbacks(OnLoadReadOnlyVersionListSuccess, OnLoadReadOnlyVersionListFailure), null);\n                m_ResourceManager.m_ResourceHelper.LoadBytes(Utility.Path.GetRemotePath(Path.Combine(m_ResourceManager.m_ReadWritePath, LocalVersionListFileName)), new LoadBytesCallbacks(OnLoadReadWriteVersionListSuccess, OnLoadReadWriteVersionListFailure), null);\n            }\n\n            private void SetCachedFileSystemName(ResourceName resourceName, string fileSystemName)\n            {\n                GetOrAddCheckInfo(resourceName).SetCachedFileSystemName(fileSystemName);\n            }","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/Resource/ResourceManager.ResourceChecker.cs#L55-L91","documentation":"CheckResources verifies that the ResourceManager's read-only path (ReadOnlyPath, where bundled/package resources live) is a non-empty string before loading the local version list. An empty or null path means the framework cannot locate read-only resources, so it throws this GameFrameworkException.","triggerScenarios":"Calling CheckResources when resourceComponent.ReadOnlyPath (or ResourceManager.m_ReadOnlyPath) was never assigned or was set to string.Empty, typically because the ResReaderMode/ReadOnlyPath config was not initialized before the check.","commonSituations":"Skipping the ResourceComponent inspector configuration; wiping ReadOnlyPath in a custom editor script; initializing resources in a stripped scene where the ResourceComponent defaults were not applied.","solutions":["Set resourceComponent.ReadOnlyPath (usually Application.streamingAssetsPath or a platform-specific path) before calling CheckResources.","Verify the GameFramework ResourceComponent inspector has a valid ReadOnlyPath configured for the active platform.","Add a null/empty assertion on ReadOnlyPath in your own bootstrap prior to invoking CheckResources."],"exampleFix":"// before\nm_ResourceComponent.ReadOnlyPath = string.Empty;\nm_ResourceComponent.CheckResources(); // throws\n\n// after\n#if UNITY_ANDROID\nm_ResourceComponent.ReadOnlyPath = Application.streamingAssetsPath;\n#else\nm_ResourceComponent.ReadOnlyPath = Utility.Path.GetRegularPath(Application.dataPath);\n#endif\nm_ResourceComponent.CheckResources();","handlingStrategy":"validation","validationCode":"if (string.IsNullOrEmpty(m_ResourceComponent.ReadOnlyPath))\n    m_ResourceComponent.ReadOnlyPath = Application.streamingAssetsPath;\nif (string.IsNullOrEmpty(m_ResourceComponent.ReadOnlyPath))\n    throw new InvalidOperationException(\"ReadOnlyPath must be configured before CheckResources\");","typeGuard":null,"tryCatchPattern":"try { m_ResourceComponent.CheckResources(); }\ncatch (GameFrameworkException ex) when (ex.Message == \"Read-only path is invalid.\")\n{\n    Debug.LogError(\"ReadOnlyPath not set; configure the ResourceComponent for this platform.\");\n}","preventionTips":["Set ReadOnlyPath per platform in a dedicated bootstrap method before any resource call.","Verify ResourceComponent inspector values in a CI/editor smoke test.","Never clear ReadOnlyPath at runtime."],"tags":["gameframework","resource","config","empty-path"],"backgroundTag":"empty-required-field","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"}