MaterialDesignInXAML/MaterialDesignInXamlToolkit · error · InvalidOperationException
Did not find repository root
Error message
Did not find repository root
What it means
PathHelper.FindRepoRoot walks upward from the current working directory looking for a directory literally named '.git'; if the loop reaches the filesystem root without finding one it throws InvalidOperationException. This is an environment probe used by the MaterialDesign resource-generation codegen tool to anchor its hard-coded relative output paths (e.g. ..\..\..\..\MaterialDesignColors.Wpf\Themes). It throws purely because the process was started from outside any git checkout, so the tool cannot know where to write generated files.
Source
Thrown at src/MaterialDesignToolkit.ResourceGeneration/PathHelper.cs:20
public static class PathHelper
{
private static readonly Lazy<string> _repoRoot = new(FindRepoRoot);
public static string RepositoryRoot => _repoRoot.Value;
private static string FindRepoRoot()
{
for (string? currentDirectory = Path.GetFullPath(".");
!string.IsNullOrEmpty(Path.GetDirectoryName(currentDirectory));
currentDirectory = Path.GetDirectoryName(currentDirectory))
{
if (Directory.Exists(Path.Combine(currentDirectory!, ".git")))
{
return currentDirectory!;
}
}
throw new InvalidOperationException("Did not find repository root");
}
}
View on GitHub (pinned to 98edec3a0b)
Solutions
- Run the generator with its working directory set to a folder inside the cloned repository (e.g. the src/MaterialDesignToolkit.ResourceGeneration project folder), not from /tmp, ~, or the bin/ output directory.
- Confirm a real .git directory exists in an ancestor of the working directory with 'git rev-parse --git-dir'; if that prints a path, .git is present.
- If you intentionally lack .git (archive build), make FindRepoRoot accept an override such as the MATERIALDESIGN_REPO_ROOT env var, or a '.repo-root' marker file, before falling back to the throw.
- If you are in a git worktree (where .git is a file), change the probe to also accept a .git file, or use LibGit2Sharp/Native git to resolve the root instead of Directory.Exists.
- Wrap the access to PathHelper.RepositoryRoot so the InvalidOperationException is caught and rethrown with the offending start path for faster diagnosis.
Example fix
// before
private static string FindRepoRoot()
{
for (string? currentDirectory = Path.GetFullPath(".");
!string.IsNullOrEmpty(Path.GetDirectoryName(currentDirectory));
currentDirectory = Path.GetDirectoryName(currentDirectory))
{
if (Directory.Exists(Path.Combine(currentDirectory!, ".git")))
return currentDirectory!;
}
throw new InvalidOperationException("Did not find repository root");
}
// after
private static string FindRepoRoot()
{
var fromEnv = Environment.GetEnvironmentVariable("MATERIALDESIGN_REPO_ROOT");
if (!string.IsNullOrWhiteSpace(fromEnv) && Directory.Exists(fromEnv))
return Path.GetFullPath(fromEnv);
for (string? currentDirectory = Path.GetFullPath(".");
!string.IsNullOrEmpty(Path.GetDirectoryName(currentDirectory));
currentDirectory = Path.GetDirectoryName(currentDirectory))
{
var git = Path.Combine(currentDirectory!, ".git");
// accept directory, git-worktree pointer file, or a marker file for archive builds
if (Directory.Exists(git) || File.Exists(git) ||
File.Exists(Path.Combine(currentDirectory!, ".repo-root")))
return currentDirectory!;
}
throw new InvalidOperationException(
$"Did not find repository root starting from '{Path.GetFullPath(".")}'. " +
"Run from inside the repo checkout or set MATERIALDESIGN_REPO_ROOT.");
} Defensive patterns
Strategy: validation
Validate before calling
string cwd = Path.GetFullPath(".");
bool foundGit = false;
for (string? d = cwd; !string.IsNullOrEmpty(Path.GetDirectoryName(d)); d = Path.GetDirectoryName(d))
{
if (Directory.Exists(Path.Combine(d!, ".git")) || File.Exists(Path.Combine(d!, ".git")))
{
foundGit = true;
break;
}
}
if (!foundGit)
throw new InvalidOperationException(
$"Not running inside a git checkout (cwd={cwd}). cd into the repo or set MATERIALDESIGN_REPO_ROOT."); Type guard
// predicate a caller can check before touching PathHelper.RepositoryRoot
static bool IsInsideRepo(string path) =>
EnumerateAncestors(Path.GetFullPath(path)).Any(d =>
Directory.Exists(Path.Combine(d, ".git")) || File.Exists(Path.Combine(d, ".git")));
static IEnumerable<string> EnumerateAncestors(string dir)
{
for (string? d = dir; !string.IsNullOrEmpty(Path.GetDirectoryName(d)); d = Path.GetDirectoryName(d))
yield return d!;
} Try / catch
try
{
var root = PathHelper.RepositoryRoot;
}
catch (InvalidOperationException ex) when (ex.Message.Contains("repository root"))
{
// report cwd + hint rather than letting the generic throw propagate
throw new InvalidOperationException(
$"{ex.Message} (search started from '{Path.GetFullPath(".")}')", ex);
} Prevention
- Always run dotnet run on the ResourceGeneration project from within the cloned repository tree, never from /tmp, ~, or the bin folder.
- Document the required working directory in the project README so CI/run scripts set it explicitly.
- Add a launchSettings.json with a workingDirectory pointing at the project folder so IDE runs anchor correctly.
- For archive/ZIP builds that lack .git, ship a .repo-root marker file or accept a MATERIALDESIGN_REPO_ROOT env override.
When it happens
Trigger: Running the ResourceGeneration console app with a working directory that is not inside the repository tree, running it from a source tarball/zip export that omits the .git folder, or running it under CI that does a shallow/git-archive checkout without a .git directory. The check is Directory.Exists(<dir>/.git), so a worktree whose .git is a file (git worktree) instead of a directory will also fail this test.
Common situations: Running dotnet run on the generator from the wrong folder; copying the source tree without the .git metadata; building in a sandbox/container where the source was rsync'd without hidden dirs; using 'git archive' or downloading the GitHub ZIP (neither includes .git); switching to a git worktree where .git is a pointer file rather than a folder.
Related errors
- The input document does not contain a root
- The attribute 'class' was not found
- Unable to map foreground color from class {liClass}
AI-assisted analysis of MaterialDesignInXAML/MaterialDesignInXamlToolkit@98edec3a0b (2026-08-13).
Data as JSON: /api/errors/d6b7f209f1c13439.
Report an issue: GitHub.