git-ecosystem/git-credential-manager · error · Trace2Exception
Failed to enumerate Git remotes
Error message
Failed to enumerate Git remotes
What it means
Thrown by Git.GetRemotes when `git remote -v` exits with an unexpected code. Exit 128 with 'not a git repository' in stderr is handled gracefully (yields nothing), so this error signals a different git failure while enumerating remotes, such as a corrupted config or a failing git executable.
Solutions
- Run `git remote -v` manually to see the underlying git error
- Validate and repair .git/config (remove malformed [remote] sections or run `git config --local --list`)
- Run `git fsck` to check repository integrity
- Confirm `git --version` works and the binary is not corrupted
Example fix
// before
foreach (var r in git.GetRemotes()) { ... } // throws on corrupt config
// after
IEnumerable<GitRemote> remotes;
try { remotes = git.GetRemotes(); }
catch (GitException) { remotes = Enumerable.Empty<GitRemote>(); } Defensive patterns
Strategy: try-catch
Validate before calling
var probe = Process.Run("git", "remote -v", workingDir);
bool remotesReadable = probe.ExitCode == 0 || (probe.ExitCode == 128 && probe.Stderr.Contains("not a git repository")); Type guard
bool TryGetRemotes(Git git, out IReadOnlyList<GitRemote> remotes) { try { remotes = git.GetRemotes().ToList(); return true; } catch (GitException) { remotes = Array.Empty<GitRemote>(); return false; } } Try / catch
try { foreach (var r in git.GetRemotes()) YieldRemote(r); }
catch (GitException ex) { log.Warn($"Remote enumeration failed: {ex.Message}"); } Prevention
- Do not hand-edit .git/config while the app runs; use git config commands
- Validate config syntax after scripted edits with `git config --local --list`
- Keep the repo free of disk errors (`git fsck`)
- Check remotes only inside directories that pass IsInsideRepository
When it happens
Trigger: Calling GetRemotes (or the `remotes` property) in a repository where `git remote -v` fails with a code other than 0 or the handled 128/not-a-repository case — corrupted .git/config, unreadable repo, broken git install.
Common situations: Manually edited or corrupt .git/config with malformed remote sections; repository on a failing disk; git version too old to parse the config.
Understand the failure class
Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.
Related errors
- Failed to get current Git repository
- Failed to enumerate all Git configuration entries
- Failed to start helper process
- helper error ( )
- Cannot prompt because terminal prompts have been disabled.
AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11).
Data as JSON: /api/errors/510d49155d80b350.
Report an issue: GitHub.
Appendix: source
Thrown at src/Core/Git.cs:197
// Redirect stderr so we can check for 'not a git repository' errors
git.StartInfo.RedirectStandardError = true;
git.Start(Trace2ProcessClass.Git);
// To avoid deadlocks, always read the output stream first and then wait
// TODO: don't read in all the data at once; stream it
string data = git.StandardOutput.ReadToEnd();
string stderr = git.StandardError.ReadToEnd();
git.WaitForExit();
switch (git.ExitCode)
{
case 0: // OK
break;
case 128 when stderr.Contains("not a git repository"): // Not inside a Git repository
yield break;
default:
var message = "Failed to enumerate Git remotes";
_trace.WriteLine($"{message} (exit={git.ExitCode})");
throw CreateGitException(git, message, _trace2);
}
string[] lines = data.Split('\n');
// Remotes are always output in groups of two (fetch and push)
for (int i = 0; i + 1 < lines.Length; i += 2)
{
// The fetch URL is written first, followed by the push URL
string[] fetchLine = lines[i].Split();
string[] pushLine = lines[i + 1].Split();
// Remote name is always first (and should match between fetch/push)
string remoteName = fetchLine[0];
// The next part, if present, is the URL
string fetchUrl = null;
string pushUrl = null;
if (fetchLine.Length > 1 && !string.IsNullOrWhiteSpace(fetchLine[1])) fetchUrl = fetchLine[1].TrimEnd();View on GitHub (pinned to e8ce762cd0)