{"record":{"id":"c2ee862bdd16b3db","repo":"EllanJiang/GameFramework","slug":"stream-is-invalid","errorCode":null,"errorMessage":"Stream is invalid.","messagePattern":"Stream is invalid\\.","errorType":"validation","errorClass":"GameFrameworkException","httpStatus":null,"severity":"error","filePath":"GameFramework/FileSystem/FileSystem.cs","lineNumber":65,"sourceCode":"        /// </summary>\n        /// <param name=\"fullPath\">文件系统完整路径。</param>\n        /// <param name=\"access\">文件系统访问方式。</param>\n        /// <param name=\"stream\">文件系统流。</param>\n        private FileSystem(string fullPath, FileSystemAccess access, FileSystemStream stream)\n        {\n            if (string.IsNullOrEmpty(fullPath))\n            {\n                throw new GameFrameworkException(\"Full path is invalid.\");\n            }\n\n            if (access == FileSystemAccess.Unspecified)\n            {\n                throw new GameFrameworkException(\"Access is invalid.\");\n            }\n\n            if (stream == null)\n            {\n                throw new GameFrameworkException(\"Stream is invalid.\");\n            }\n\n            m_FullPath = fullPath;\n            m_Access = access;\n            m_Stream = stream;\n            m_FileDatas = new Dictionary<string, int>(StringComparer.Ordinal);\n            m_BlockDatas = new List<BlockData>();\n            m_FreeBlockIndexes = new GameFrameworkMultiDictionary<int, int>();\n            m_StringDatas = new SortedDictionary<int, StringData>();\n            m_FreeStringIndexes = new Queue<int>();\n            m_FreeStringDatas = new Queue<StringData>();\n\n            m_HeaderData = default(HeaderData);\n            m_BlockDataOffset = 0;\n            m_StringDataOffset = 0;\n            m_FileDataOffset = 0;\n\n            Utility.Marshal.EnsureCachedHGlobalSize(CachedBytesLength);","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/EllanJiang/GameFramework/blob/d0c010b05167c58e92350449d04864a91ca13fd2/GameFramework/FileSystem/FileSystem.cs#L47-L83","documentation":"Constructor guard in the private FileSystem(fullPath, access, stream): thrown when the stream argument is null. After validating fullPath and access, the constructor requires a live underlying FileSystemStream to read or write file-system data; a null stream means the caller failed to open the underlying file.","triggerScenarios":"Calling FileSystem.Create or FileSystem.Open with a null stream — typically the result of a failed File.Open/stream factory call whose null return was not checked.","commonSituations":"File.Open returning null on missing file or permission error (GameFramework-style APIs often return null instead of throwing); a custom FileSystemStream implementation factory returning null on failure.","solutions":["Check the stream creation result for null before passing it to Create/Open","Ensure the archive file exists or is creatable at fullPath (directory present, permissions OK)","Make the stream factory throw or log instead of silently returning null","Use File access APIs that throw on failure to get a real error message about why the stream is missing"],"exampleFix":"// before\nvar stream = File.Open(fullPath); // returns null on failure\nvar fs = FileSystem.Create(fullPath, access, stream, ...); // throws here\n// after\nvar stream = File.Open(fullPath);\nif (stream == null) throw new InvalidOperationException(\"Failed to open \" + fullPath);\nvar fs = FileSystem.Create(fullPath, access, stream, ...);","handlingStrategy":"type-guard","validationCode":"if (stream == null) throw new ArgumentNullException(nameof(stream));\nFileSystem.Create(fullPath, access, stream, maxFileCount, maxBlockCount);","typeGuard":"bool HasValidStream(FileSystemStream s) => s != null;","tryCatchPattern":"try { var fs = FileSystem.Create(path, access, stream, fc, bc); }\ncatch (GameFrameworkException ex) when (ex.Message == \"Stream is invalid.\") { Log.Error(\"Stream creation failed earlier — check the open call's null return\"); }","preventionTips":["Always null-check the result of GameFramework File.Open/stream factories — they return null instead of throwing","Ensure the archive's parent directory exists before opening the stream","Wrap stream creation so failures log the underlying cause"],"tags":["gameframework","filesystem","null-argument"],"backgroundTag":"null-argument","analyzedSha":"d0c010b05167c58e92350449d04864a91ca13fd2","analyzedAt":"2026-09-15T13:37:15.352Z","contentChangedAt":"2026-09-15T13:37:15.352Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}