PrismLibrary/Prism · critical · InvalidOperationException

IModuleCatalog

Error message

IModuleCatalog

What it means

Prism's PrismBootstrapperBase.RegisterRequiredTypes throws this InvalidOperationException when the module catalog (_moduleCatalog) is null at the point where required types are registered with the DI container. Prism requires an IModuleCatalog instance to function (it drives module discovery/loading), so a null catalog is an unrecoverable application configuration error. The message is just the type name 'IModuleCatalog', so it looks cryptic but means 'you never provided a module catalog to the bootstrapper'.

Solutions

  1. Override CreateModuleCatalog() in your bootstrapper and return a catalog instance (e.g. return new ModuleCatalog(); or ConfigureModuleCatalog variant for directory/xaml catalogs).
  2. If you override RegisterRequiredTypes, ensure _moduleCatalog is set (call CreateModuleCatalog or assign the field) before calling base.RegisterRequiredTypes(containerRegistry).
  3. Check the order of operations: Run() must complete CreateModuleCatalog/ConfigureModuleCatalog before RegisterRequiredTypes is invoked; do not call Run twice or call RegisterRequiredTypes manually early.
  4. On Prism version upgrades, migrate to the current bootstrapper base (PrismBootstrapper) and let it create the default ModuleCatalog instead of a hand-rolled one.

Example fix

// before
public class AppBootstrapper : PrismBootstrapperBase
{
    protected override void RegisterRequiredTypes(IContainerRegistry containerRegistry)
    {
        // base call throws: _moduleCatalog is null
        base.RegisterRequiredTypes(containerRegistry);
    }
}
// after
public class AppBootstrapper : PrismBootstrapperBase
{
    protected override IModuleCatalog CreateModuleCatalog()
    {
        return new ModuleCatalog(); // or a directory/XAML catalog
    }
}
Defensive patterns

Strategy: validation

Validate before calling

// In a custom bootstrapper, before startup:
protected override IModuleCatalog CreateModuleCatalog()
{
    var catalog = new ModuleCatalog();
    if (catalog == null) throw new InvalidOperationException(
        "CreateModuleCatalog must return a non-null IModuleCatalog instance.");
    return catalog;
}

Type guard

bool HasModuleCatalog(PrismBootstrapperBase b, Func<IModuleCatalog> accessor)
    => accessor?.Invoke() is IModuleCatalog; // false when null/missing

Try / catch

try
{
    bootstrapper.Run();
}
catch (InvalidOperationException ex) when (ex.Message == "IModuleCatalog")
{
    // log: bootstrapper was not configured with a module catalog
    // fix configuration: implement CreateModuleCatalog()
}

Prevention

When it happens

Trigger: Calling base.RegisterRequiredTypes (indirectly via Run/ConfigureViewModelLocator startup flow) when the CreateModuleCatalog() override was not implemented, returned null, or the _moduleCatalog field was never assigned before registration runs.

Common situations: 1) Developer overrides RegisterRequiredTypes or CreateModuleCatalog incorrectly or forgets to call base in a custom bootstrapper. 2) Upgrading Prism versions (Prism 8+ unified bootstrappers) where a custom bootstrapper no longer sets the catalog the old way. 3) Copying a bootstrapper template and deleting CreateModuleCatalog because the app 'doesn't use modules'. 4) Constructing PrismBootstrapperBase-derived class manually and calling Run before initialization populated _moduleCatalog.

Related errors


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

Appendix: source

Thrown at src/Wpf/Prism.Wpf/PrismBootstrapperBase.cs:105

        /// <summary>
        /// Creates the <see cref="IModuleCatalog"/> used by Prism.
        /// </summary>
        ///  <remarks>
        /// The base implementation returns a new ModuleCatalog.
        /// </remarks>
        protected virtual IModuleCatalog CreateModuleCatalog()
        {
            return new ModuleCatalog();
        }

        /// <summary>
        /// Registers all types that are required by Prism to function with the container.
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected virtual void RegisterRequiredTypes(IContainerRegistry containerRegistry)
        {
            if (_moduleCatalog == null)
                throw new InvalidOperationException("IModuleCatalog");

            containerRegistry.RegisterRequiredTypes(_moduleCatalog);
        }

        /// <summary>
        /// Used to register types with the container that will be used by your application.
        /// </summary>
        protected abstract void RegisterTypes(IContainerRegistry containerRegistry);

        /// <summary>
        /// Configures the <see cref="IRegionBehaviorFactory"/>.
        /// This will be the list of default behaviors that will be added to a region.
        /// </summary>
        protected virtual void ConfigureDefaultRegionBehaviors(IRegionBehaviorFactory regionBehaviors)
        {
            regionBehaviors?.RegisterDefaultRegionBehaviors();
        }

View on GitHub (pinned to 358118cd64)