git-ecosystem/git-credential-manager · error · Trace2Exception

Missing 'pat' in response

Error message

Missing 'pat' in response

What it means

When the helper reports response mode 'pat', the response dictionary must also contain a 'pat' key with the personal access token. If mode is 'pat' but no token value accompanies it, the contract between helper and core is violated and this Trace2Exception is thrown — a credential cannot be constructed without the token.

Solutions

  1. Update Git Credential Manager to a matching, current version so helper and core agree on the response contract
  2. Capture GCM_TRACE output and run the helper manually to inspect the raw key/value response
  3. Retry the authentication flow and complete the PAT entry fully
  4. If writing a custom helper, always emit both mode=pat and the pat key together

Example fix

// before
if (!resultDict.TryGetValue("pat", out string pat)) throw new Trace2Exception(Context.Trace2, "Missing 'pat' in response");
// after (helper side: ensure both keys emitted)
if (!string.IsNullOrEmpty(collectedPat))
{
    output["mode"] = "pat";
    output["pat"] = collectedPat;
}
Defensive patterns

Strategy: validation

Validate before calling

// Caller-side sanity check pattern: confirm helper contract before trusting a custom helper
// (run helper manually and parse output)
var output = RunHelper("github get-authenticator");
bool valid = output.ContainsKey("mode") &&
             (output["mode"] != "pat" || output.ContainsKey("pat"));
if (!valid) throw new InvalidOperationException("Helper response incomplete for pat mode.");

Try / catch

try
{
    var result = await auth.GetAuthenticationAsync(uri, userName);
}
catch (Trace2Exception ex) when (ex.Message == "Missing 'pat' in response")
{
    // retry the prompt once, then surface a helper-contract error
    trace.WriteLine("Helper emitted mode=pat without token; retrying.");
    throw;
}

Prevention

When it happens

Trigger: Helper returns mode=pat but the 'pat' entry is absent: the helper's PAT collection step was interrupted, an incompatible/buggy helper version emitted mode without the token, or the dictionary was truncated during parsing.

Common situations: User cancels midway through the PAT dialog but helper still emits mode=pat; version skew between GCM core and UI helper after a partial upgrade; custom/third-party helper implementations that forget the pat key.

Related errors


AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11). Data as JSON: /api/errors/bb3d5add8548001a. Report an issue: GitHub.

Appendix: source

Thrown at src/GitHub/GitHubAuthentication.cs:317

            }

            if (!GitHubHostProvider.IsGitHubDotCom(targetUri))
                promptArgs.AppendFormat(" --enterprise-url {0}", QuoteCmdArg(targetUri.ToString()));
            if (!string.IsNullOrWhiteSpace(userName)) promptArgs.AppendFormat(" --username {0}", QuoteCmdArg(userName));

            IDictionary<string, string> resultDict = await InvokeHelperAsync(command, promptArgs.ToString(), null);

            if (!resultDict.TryGetValue("mode", out string responseMode))
            {
                throw new Trace2Exception(Context.Trace2, "Missing 'mode' in response");
            }

            switch (responseMode.ToLowerInvariant())
            {
                case "pat":
                    if (!resultDict.TryGetValue("pat", out string pat))
                    {
                        throw new Trace2Exception(Context.Trace2, "Missing 'pat' in response");
                    }

                    return new AuthenticationPromptResult(
                        AuthenticationModes.Pat, new GitCredential(userName, pat));

                case "browser":
                    return new AuthenticationPromptResult(AuthenticationModes.Browser);

                case "device":
                    return new AuthenticationPromptResult(AuthenticationModes.Device);

                case "basic":
                    if (!resultDict.TryGetValue("username", out userName))
                    {
                        throw new Trace2Exception(Context.Trace2, "Missing 'username' in response");
                    }

                    if (!resultDict.TryGetValue("password", out string password))

View on GitHub (pinned to e8ce762cd0)