{"record":{"id":"7c5c79a08202f858","repo":"stride3d/stride","slug":"package-rootdirectory-is-null","errorCode":null,"errorMessage":"Package RootDirectory is null","messagePattern":"Package RootDirectory is null","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets/Package.cs","lineNumber":1238,"sourceCode":"        foreach (var folder in AssetFolders)\n        {\n            var folderPath = RootDirectory is not null ? UPath.Combine(RootDirectory, folder.Path) : folder.Path;\n            if (!existingAssetFolders.Contains(folderPath))\n            {\n                existingAssetFolders.Add(folderPath);\n            }\n        }\n        return existingAssetFolders;\n    }\n\n    public static List<PackageLoadingAssetFile> ListAssetFiles(Package package, bool listAssetsInMsbuild, bool listUnregisteredAssets)\n    {\n        var listFiles = new List<PackageLoadingAssetFile>();\n\n        // TODO Check how to handle refresh correctly as a public API\n        if (package.RootDirectory is null)\n        {\n            throw new InvalidOperationException(\"Package RootDirectory is null\");\n        }\n\n        if (!Directory.Exists(package.RootDirectory))\n        {\n            return listFiles;\n        }\n\n        // Iterate on each source folders\n        foreach (var sourceFolder in package.GetDistinctAssetFolderPaths())\n        {\n            // Lookup all files\n            foreach (var directory in FileUtility.EnumerateDirectories(sourceFolder, SearchDirection.Down))\n            {\n                foreach (var filePath in directory.GetFiles())\n                {\n                    // Don't load package via this method\n                    if (filePath.FullName.EndsWith(PackageFileExtension, StringComparison.OrdinalIgnoreCase))\n                    {","sourceCodeStart":1220,"sourceCodeEnd":1256,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets/Package.cs#L1220-L1256","documentation":"This internal refresh helper (CollectFiles) requires package.RootDirectory to be set before it can enumerate files for the package. A null RootDirectory means the package has no root folder association, so enumeration is impossible and it throws InvalidOperationException.","triggerScenarios":"Calling the package file-collection/refresh routine on a Package instance whose RootDirectory property is null — typically a package not loaded from/saved to disk.","commonSituations":"Programmatically constructed in-memory Package objects passed to refresh; deserialization that omitted RootDirectory; packages loaded from sources that don't set the root.","solutions":["Set package.RootDirectory to the package's folder before refreshing","Ensure the package is loaded via the normal load pipeline so RootDirectory is populated","Skip refresh for in-memory packages without a root directory"],"exampleFix":"// before\nRefreshPackageFiles(newInMemoryPackage);\n// after\nif (newInMemoryPackage.RootDirectory is null)\n    newInMemoryPackage.RootDirectory = packageFolder;\nRefreshPackageFiles(newInMemoryPackage);","handlingStrategy":"type-guard","validationCode":"if (package.RootDirectory is null) throw new InvalidOperationException(\"Set RootDirectory before refresh\");","typeGuard":"bool CanRefresh(Package p) => p.RootDirectory is not null && Directory.Exists(p.RootDirectory);","tryCatchPattern":"try { RefreshPackageFiles(pkg); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"RootDirectory\")) { pkg.RootDirectory = rootFolder; RefreshPackageFiles(pkg); }","preventionTips":["Never refresh in-memory packages without a root directory","Populate RootDirectory when constructing Package objects programmatically","Assert RootDirectory in package load tests"],"tags":["package","state","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}