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

Missing or invalid interaction_mode in response

Error message

Missing or invalid interaction_mode in response

What it means

When GCM needs to ask how the user wants to authenticate, it shows a prompt whose response dictionary should include an 'interaction_mode' key parseable as an InteractionMode enum. This throws when the key is absent or its value cannot be parsed, so the desired interaction mode is unknown.

Solutions

  1. Ensure the prompt/helper response includes interaction_mode with a supported value (e.g. OAuth, Browser, Device, Basic)
  2. Fix spelling/casing of the value and verify it exists in the current InteractionMode enum
  3. Upgrade GCM if the mode name is from a newer version
  4. Set the interaction mode explicitly via configuration (GCM_INTERACTIVE / credential.interactive) so the prompt path isn't relied on

Example fix

// before (helper response)
"mode=Browser"
// after
"interaction_mode=Browser"
Defensive patterns

Strategy: try-catch

Validate before calling

if (!Enum.TryParse<InteractionMode>(modeString, ignoreCase: true, out _))
    throw new ArgumentException($"'{modeString}' is not a valid InteractionMode.");

Type guard

bool TryGetInteractionMode(IDictionary<string,string> resp, out InteractionMode mode) {
    mode = default;
    return resp.TryGetValue("interaction_mode", out var s) && Enum.TryParse(s, ignoreCase: true, out mode) && Enum.IsDefined(mode);
}

Try / catch

try { /* entra auth */ }
catch (Trace2Exception ex) when (ex.Message.Contains("interaction_mode")) { /* fix prompt/helper response or set mode via config */ }

Prevention

When it happens

Trigger: GetInteractionModeAsync reads a prompt response via TryGetValue("interaction_mode", out str) and Enum.TryParse(str, ignoreCase: true, out InteractionMode choice); if either fails, the Trace2Exception is thrown. Only reached in the non-tty/prompt path (not the tty branch).

Common situations: A custom/overridden prompt or helper returns a response missing interaction_mode; a typo'd or new mode string not present in the current InteractionMode enum; version mismatch where the prompt emits a newer mode name than this GCM build understands.

Related errors


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

Appendix: source

Thrown at src/Core/Authentication/Entra/EntraAuthentication.PublicClient.cs:119

        // Show auth mode prompt
        if (Context.Settings.IsGuiPromptsEnabled && Context.SessionManager.IsDesktopSession)
        {
            if (TryFindHelperCommand(out string command, out string args))
            {
                var availableNames = available.Select(m => m.ToString().ToLowerInvariant());

                var sb = new StringBuilder(args);
                sb.Append("select-interaction-mode");
                sb.AppendFormat(" --available {0}", QuoteCmdArg(string.Join(',', availableNames)));

                IDictionary<string, string> result = await InvokeHelperAsync(command, sb.ToString());
                if (result.TryGetValue("interaction_mode", out string str) &&
                    Enum.TryParse(str, ignoreCase: true, out InteractionMode choice))
                {
                    return choice;
                }

                throw new Trace2Exception(Context.Trace2, "Missing or invalid interaction_mode in response");
            }

            // TODO: show prompt in-proc
        }

        // Show prompt in tty
        var prompt = TerminalPrompts.CreateSelection<InteractionMode>()
            .Title("Select an authentication flow")
            .AddChoices(available, m => m.GetDisplayName());
        return await prompt.ShowAsync(Context.Console, ct);
    }

    public async Task<IReadOnlyList<IEntraAccount>> GetUserAccountsAsync(CancellationToken ct = default)
    {
        IPublicClientApplication app = GetPublicAppBuilder(out _).Build();
        await RegisterCacheAsync(app);

        IEnumerable<IAccount> accounts = await app.GetAccountsAsync();

View on GitHub (pinned to e8ce762cd0)