PrismLibrary/Prism · error · InvalidOperationException
Resources.ModulePathCannotBeNullOrEmpty
Error message
Resources.ModulePathCannotBeNullOrEmpty
What it means
DirectoryModuleCatalog (.NET Framework build) throws InvalidOperationException when ModulePath is null or empty. This catalog scans a directory on disk for assemblies containing modules, so a path is mandatory. The check happens first in InnerLoad before any directory scanning or child AppDomain creation.
Solutions
- Set ModulePath to an existing directory containing your module assemblies before calling Load(): catalog.ModulePath = @".\Modules";
- If the path comes from configuration, ensure the config value is present and non-empty.
- Add a startup assertion/log if ModulePath is resolved dynamically so misconfiguration is caught early.
- Consider DirectoryModuleCatalog from the config-based setup only when directory scanning is actually needed.
Example fix
// before
var catalog = new DirectoryModuleCatalog();
catalog.Load();
// after
var catalog = new DirectoryModuleCatalog { ModulePath = @".\Modules" };
catalog.Load(); Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrEmpty(catalog.ModulePath))
throw new InvalidOperationException("DirectoryModuleCatalog.ModulePath must be set before Load()."); Type guard
static bool HasModulePath(DirectoryModuleCatalog c) => !string.IsNullOrEmpty(c.ModulePath);
Try / catch
try { catalog.Load(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("ModulePath") || ex.Message.Contains("path")) { logger.LogError(ex, "ModulePath not configured"); } Prevention
- Set ModulePath in the same place the catalog is created.
- Read the path from config with a non-empty default.
- Fail fast at startup when configured path is blank.
- Add tests mirroring production catalog construction.
When it happens
Trigger: Creating a DirectoryModuleCatalog and calling Load() without setting the ModulePath property, or setting it to an empty string.
Common situations: Configuring directory-based module discovery but forgetting ModulePath; reading the path from config and the config key is empty/missing; refactoring moved the path assignment away from catalog creation.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Resources.DirectoryNotFound (string.Format with ModulePath)
- Resources.ModulePathCannotBeNullOrEmpty
- Resources.InvalidArgumentAssemblyUri
- Resources.ConfigurationStoreCannotBeNull
- Resources.DirectoryNotFound (string.Format with ModulePath)
AI-assisted analysis of PrismLibrary/Prism@358118cd64 (2026-09-15).
Data as JSON: /api/errors/15af436b7b50d4ea.
Report an issue: GitHub.
Appendix: source
Thrown at src/Wpf/Prism.Wpf/Modularity/DirectoryModuleCatalog.net45.cs:34
/// Assemblies are loaded into a new application domain with ReflectionOnlyLoad. The application domain is destroyed
/// once the assemblies have been discovered.
///
/// The diretory catalog does not continue to monitor the directory after it has created the initialze catalog.
/// </remarks>
public class DirectoryModuleCatalog : ModuleCatalog
{
/// <summary>
/// Directory containing modules to search for.
/// </summary>
public string ModulePath { get; set; }
/// <summary>
/// Drives the main logic of building the child domain and searching for the assemblies.
/// </summary>
protected override void InnerLoad()
{
if (string.IsNullOrEmpty(ModulePath))
throw new InvalidOperationException(Resources.ModulePathCannotBeNullOrEmpty);
if (!Directory.Exists(ModulePath))
throw new InvalidOperationException(
string.Format(CultureInfo.CurrentCulture, Resources.DirectoryNotFound, ModulePath));
AppDomain childDomain = BuildChildDomain(AppDomain.CurrentDomain);
try
{
List<string> loadedAssemblies = new List<string>();
var assemblies = (
from Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()
where !(assembly is System.Reflection.Emit.AssemblyBuilder)
&& assembly.GetType().FullName != "System.Reflection.Emit.InternalAssemblyBuilder"
// TODO: Do this in a less hacky way... probably never gonna happen
&& !assembly.GetName().Name.StartsWith("xunit")
&& !string.IsNullOrEmpty(assembly.Location)View on GitHub (pinned to 358118cd64)