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

  1. Run `git remote -v` manually to see the underlying git error
  2. Validate and repair .git/config (remove malformed [remote] sections or run `git config --local --list`)
  3. Run `git fsck` to check repository integrity
  4. 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

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


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)