PrismLibrary/Prism · error · ArgumentNullException

Value cannot be null. (Parameter 'moduleCatalog')

Error message

Value cannot be null. (Parameter 'moduleCatalog')

What it means

The ModuleManager constructor throws ArgumentNullException when either the IModuleInitializer or the IModuleCatalog dependency is null. The catalog enumerates which modules to load and initialize, so a null catalog makes the module system non-functional. This is a fail-fast guard against wiring mistakes in dependency injection.

Solutions

  1. Register IModuleCatalog with the DI container (e.g. in CreateWindowScope/App: containerRegistry.RegisterSingleton<IModuleCatalog, ModuleCatalog>()) before ModuleManager is resolved.
  2. If constructing manually, pass a concrete ModuleCatalog instance: new ModuleManager(new ModuleInitializer(...), new ModuleCatalog()).
  3. Check ordering: ensure the module catalog is populated (via ConfigureModuleCatalog) before ModuleManager.Run() is invoked.

Example fix

// before
services.AddSingleton<ModuleManager>(); // IModuleCatalog never registered -> null
// after
services.AddSingleton<IModuleCatalog, ModuleCatalog>();
services.AddSingleton<IModuleInitializer, ModuleInitializer>();
services.AddSingleton<ModuleManager>();
Defensive patterns

Strategy: validation

Validate before calling

var catalog = serviceProvider.GetService<IModuleCatalog>();
if (catalog is null)
    throw new InvalidOperationException("IModuleCatalog is not registered; register it before resolving ModuleManager.");
var manager = new ModuleManager(initializer, catalog);

Type guard

bool IsValidDeps(IModuleInitializer i, IModuleCatalog c) => i is not null && c is not null;

Prevention

When it happens

Trigger: Constructing ModuleManager directly with `new ModuleManager(initializer, null)` or resolving it from a DI container where IModuleCatalog was never registered, so the container injects null.

Common situations: Custom PrismApplication/maui startup code that forgets `containerRegistry.RegisterSingleton<IModuleCatalog, ModuleCatalog>()`; manual instantiation in unit tests; replacing Prism's DI registration pipeline and losing the catalog registration.

Related errors


AI-assisted analysis of PrismLibrary/Prism@358118cd64 (2026-09-15). Data as JSON: /api/errors/2950d54487f7e7e6. Report an issue: GitHub.

Appendix: source

Thrown at src/Maui/Prism.Maui/Modularity/ModuleManager.cs:48

    {
        add => throw new NotSupportedException();
        remove => throw new NotSupportedException();
    }

    /// <summary>
    /// The module initializer.
    /// </summary>
    protected IModuleInitializer ModuleInitializer { get; }

    /// <summary>
    /// Initializes an instance of the <see cref="ModuleManager"/> class.
    /// </summary>
    /// <param name="moduleInitializer">Service used for initialization of modules.</param>
    /// <param name="moduleCatalog">Catalog that enumerates the modules to be loaded and initialized.</param>
    public ModuleManager(IModuleInitializer moduleInitializer, IModuleCatalog moduleCatalog)
    {
        ModuleInitializer = moduleInitializer ?? throw new ArgumentNullException(nameof(moduleInitializer));
        ModuleCatalog = moduleCatalog ?? throw new ArgumentNullException(nameof(moduleCatalog));
    }

    /// <summary>
    /// Initializes the modules marked as <see cref="InitializationMode.WhenAvailable"/> in the <see cref="ModuleCatalog"/>.
    /// </summary>
    public void Run()
    {
        LoadModulesWhenAvailable();
    }

    /// <summary>
    /// Loads and initializes the module in the <see cref="IModuleCatalog"/> with the name <paramref name="moduleName"/>.
    /// </summary>
    /// <param name="moduleName">Name of the module requested for initialization.</param>
    public void LoadModule(string moduleName)
    {
        var modules = ModuleCatalog.Modules.Where(m => m.ModuleName == moduleName);
        if (modules == null || modules.Count() == 0)

View on GitHub (pinned to 358118cd64)