{"record":{"id":"e7a5d26580e36c6c","repo":"stride3d/stride","slug":"a-virtual-file-provider-with-the-root-path-provider-rootpath","errorCode":null,"errorMessage":"A Virtual File Provider with the root path \"{provider.RootPath}\" already exists.","messagePattern":"A Virtual File Provider with the root path \"(.+?)\" already exists\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.IO/VirtualFileSystem.cs","lineNumber":120,"sourceCode":"    /// <value>The providers.</value>\n    public static IEnumerable<IVirtualFileProvider> Providers\n    {\n        get\n        {\n            return providers.Values;\n        }\n    }\n\n    /// <summary>\n    /// Registers the specified virtual file provider at the specified mount location.\n    /// </summary>\n    /// <param name=\"provider\">The provider.</param>\n    public static void RegisterProvider(IVirtualFileProvider provider)\n    {\n        if (provider.RootPath != null)\n        {\n            if (!providers.TryAdd(provider.RootPath, provider))\n                throw new InvalidOperationException($\"A Virtual File Provider with the root path \\\"{provider.RootPath}\\\" already exists.\");\n        }\n    }\n\n    /// <summary>\n    /// Unregisters the specified virtual file provider.\n    /// </summary>\n    /// <param name=\"provider\">The provider.</param>\n    /// <param name=\"dispose\">Indicate that the provider should be disposed, if it inherits from IDisposable interface.</param>\n    public static void UnregisterProvider(IVirtualFileProvider provider, bool dispose = true)\n    {\n        var mountPoints = providers.Where(x => x.Value == provider).ToArray();\n        foreach (var mountPoint in mountPoints)\n            providers.Remove(mountPoint.Key);\n    }\n\n    /// <summary>\n    /// Mounts the specified path in the specified virtual file mount point.\n    /// </summary>","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.IO/VirtualFileSystem.cs#L102-L138","documentation":"VirtualFileSystem.RegisterProvider maintains a static registry keyed by provider RootPath; only one provider may exist per root path. If a provider with a non-null RootPath is registered and another provider (or the same one twice) already occupies that key, the TryAdd fails and this InvalidOperationException is thrown.","triggerScenarios":"Calling VirtualFileSystem.RegisterProvider twice with providers having the same RootPath (e.g. mounting '/assets' twice), or registering a provider whose root path collides with a provider auto-registered during engine startup.","commonSituations":"Game/plugins initializing asset systems in both app code and a bootstrap that runs twice (e.g. constructor + static initializer); test suites creating providers per test without unregistering via UnregisterProvider; duplicate mount entries in config.","solutions":["Check providers with VirtualFileSystem.GetProvider(rootPath) before calling RegisterProvider, or skip registration if it returns non-null.","Call VirtualFileSystem.UnregisterProvider(rootPath) for stale providers before re-registering.","Remove duplicate initialization code paths so the provider is registered exactly once per process.","Use a distinct RootPath for the new provider if both mounts are genuinely needed."],"exampleFix":"// before\nVirtualFileSystem.RegisterProvider(new DatabaseFileProvider(mount));\n// after\nif (VirtualFileSystem.GetProvider(mount) == null)\n    VirtualFileSystem.RegisterProvider(new DatabaseFileProvider(mount));","handlingStrategy":"validation","validationCode":"if (VirtualFileSystem.GetProvider(provider.RootPath) == null)\n    VirtualFileSystem.RegisterProvider(provider);","typeGuard":null,"tryCatchPattern":"try { VirtualFileSystem.RegisterProvider(provider); }\ncatch (InvalidOperationException) { /* provider for this root already mounted — reuse it */ }","preventionTips":["Always call GetProvider first or register inside a static lazy singleton","Pair every RegisterProvider with UnregisterProvider in test teardown","Use unique, namespaced root paths per module"],"tags":["filesystem","dotnet","virtual-filesystem"],"backgroundTag":"file-already-exists","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}