PrismLibrary/Prism · error · InvalidOperationException

Resources.DirectoryNotFound (string.Format with ModulePath)

Error message

Resources.DirectoryNotFound (string.Format with ModulePath)

What it means

DirectoryModuleCatalog (.NET Framework build) throws InvalidOperationException with a formatted DirectoryNotFound message when ModulePath is non-empty but the directory does not exist on disk. The message includes the offending path so the misconfiguration is obvious. Thrown before creating the child AppDomain used for assembly scanning.

Solutions

  1. Verify the directory exists before Load: Directory.Exists(path), create it if appropriate with Directory.CreateDirectory(path).
  2. Use an absolute path (Path.Combine(AppContext.BaseDirectory or AppDomain.CurrentDomain.BaseDirectory, "Modules")) instead of a relative one.
  3. Ensure the Modules folder is included in deployment (copy-to-output settings for module projects).
  4. Log the resolved ModulePath at startup to catch environment path drift.

Example fix

// before
catalog.ModulePath = @"Modules"; // relative, breaks under test runner

// after
catalog.ModulePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules");
Defensive patterns

Strategy: validation

Validate before calling

if (!Directory.Exists(catalog.ModulePath))
    Directory.CreateDirectory(catalog.ModulePath); // or fail with a clear message

Type guard

static bool ModulePathExists(string path) => !string.IsNullOrEmpty(path) && Directory.Exists(path);

Try / catch

try { catalog.Load(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("directory") || ex.Message.Contains(ModulePath)) { logger.LogError(ex, "Modules directory missing: {Path}", ModulePath); }

Prevention

When it happens

Trigger: Setting DirectoryModuleCatalog.ModulePath to a directory that does not exist (typo, wrong working directory, missing deployment folder) and calling Load().

Common situations: ClickOnce/publish deployments where the Modules folder was not copied; relative path resolved against an unexpected working directory (e.g. when run under a test runner or service); path renamed between environments.

Related errors


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

Appendix: source

Thrown at src/Wpf/Prism.Wpf/Modularity/DirectoryModuleCatalog.net45.cs:37

    /// 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)
                                     select assembly.Location
                                 );

View on GitHub (pinned to 358118cd64)