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
- Run the sample from a directory within the repo (e.g., the project folder) so the upward search reaches the Plugins folder quickly.
- Increase the maxAttempts parameter in the SearchPath call to accommodate deeper directory nesting.
- Copy or symlink the Plugins directory into the app's output folder.
- 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
- Make resource paths configurable via environment variables.
- Ship required directories as content with CopyToOutputDirectory in the .csproj.
- Always run samples from within the repo structure during development.
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
- File '{fileName}' not found.
- Plugin creation failed for {pluginName}
- Directory {path} not found in repository.
- Invalid choice
- Configuration is not setup correctly.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/d6ab0b3a543463b9.
Report an issue: GitHub.