microsoft/semantic-kernel · critical · DirectoryNotFoundException

Plugins directory not found. The app needs the plugins from

Error message

Plugins directory not found. The app needs the plugins from the repo to work.

What it means

RepoFiles.SearchPath walks up to maxAttempts parent directories from the current directory looking for a folder (e.g., 'Plugins'). If it is not found within the attempt budget, the method throws DirectoryNotFoundException. This is used to locate the sample's plugins folder relative to the repo root at runtime.

Source

Thrown at dotnet/samples/Demos/TelemetryWithAppInsights/RepoUtils/RepoFiles.cs:32

        const string Folder = "prompt_template_samples";

        static bool SearchPath(string pathToFind, out string result, int maxAttempts = 10)
        {
            var currDir = Path.GetFullPath(Assembly.GetExecutingAssembly().Location);
            bool found;
            do
            {
                result = Path.Join(currDir, pathToFind);
                found = Directory.Exists(result);
                currDir = Path.GetFullPath(Path.Combine(currDir, ".."));
            } while (maxAttempts-- > 0 && !found);

            return found;
        }

        if (!SearchPath(Folder, out var path))
        {
            throw new DirectoryNotFoundException("Plugins directory not found. The app needs the plugins from the repo to work.");
        }

        return path;
    }
}

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Run the sample from a directory within the repo (e.g., the project folder) so the upward search reaches the Plugins folder quickly.
  2. Increase the maxAttempts parameter in the SearchPath call to accommodate deeper directory nesting.
  3. Copy or symlink the Plugins directory into the app's output folder.
  4. Make the Plugins path configurable via environment variable or appsettings so it doesn't depend on the repo structure.

Example fix

// before
if (!SearchPath(Folder, out var path))
{
    throw new DirectoryNotFoundException("Plugins directory not found. The app needs the plugins from the repo to work.");
}

// after — allow override via environment variable, then fall back to search
var pluginsDir = Environment.GetEnvironmentVariable("PLUGINS_DIR");
if (!string.IsNullOrEmpty(pluginsDir) && Directory.Exists(pluginsDir))
    return pluginsDir;
if (!SearchPath(Folder, out var path))
    throw new DirectoryNotFoundException($"Plugins directory not found at '{Folder}'. Set PLUGINS_DIR or run from within the repo.");
return path;
Defensive patterns

Strategy: validation

Validate before calling

// Check an environment override first, then verify existence
var dir = Environment.GetEnvironmentVariable("PLUGINS_DIR") ?? Path.Combine(AppContext.BaseDirectory, "Plugins");
if (!Directory.Exists(dir))
    throw new DirectoryNotFoundException($"Plugins directory not found at '{dir}'. Set PLUGINS_DIR or run from the repo.");

Try / catch

try { return RepoFiles.FindPlugins(); } catch (DirectoryNotFoundException) { /* copy plugins to output or adjust CWD */ }

Prevention

When it happens

Trigger: Running the TelemetryWithAppInsights sample from a working directory that is more than maxAttempts levels below the plugins folder, or from outside the repo entirely so the plugins folder is never an ancestor.

Common situations: Running the published app or a unit test from bin/Release/netX.0/ when the repo is deeply nested; running inside a Docker container where the repo isn't mounted; cloning the repo but not including the Plugins directory; maxAttempts is too small for deep working-directory nesting.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/d6ab0b3a543463b9. Report an issue: GitHub.