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

Must specify at least one AuthenticationModes

Error message

Must specify at least one AuthenticationModes

What it means

BitbucketAuthentication.GetCredentialsAsync validates the requested set of authentication modes before showing any prompt. If the caller passes AuthenticationModes.None (no supported auth mode), the library cannot proceed and throws ArgumentException naming the modes parameter. This is a programming/configuration error, not a runtime user action.

Solutions

  1. Check the modes argument passed to GetCredentialsAsync; ensure at least one AuthenticationModes flag (Basic, OAuth, Browser, Gcm) is set
  2. Inspect the settings controlling GetSupportedAuthenticationModesAsync (e.g. GCM_BITBUCKET_AUTHMODES / host provider config) and enable a valid mode
  3. If computing modes dynamically, guard with `if ((modes & AuthenticationModes.None) != 0 || modes == AuthenticationModes.None)` before calling

Example fix

// before
var modes = AuthenticationModes.None;
var cred = await auth.GetCredentialsAsync(uri, userName, modes);
// after
var modes = AuthenticationModes.Basic | AuthenticationModes.OAuth;
var cred = await auth.GetCredentialsAsync(uri, userName, modes);
Defensive patterns

Strategy: validation

Validate before calling

if (modes == AuthenticationModes.None)
    throw new ArgumentException("At least one auth mode required");
var cred = await auth.GetCredentialsAsync(uri, userName, modes);

Type guard

bool HasAnyMode(AuthenticationModes m) => m != AuthenticationModes.None;

Try / catch

try { await auth.GetCredentialsAsync(uri, user, modes); }
catch (ArgumentException ex) when (ex.ParamName == "modes") { /* configure a valid mode and retry */ }

Prevention

When it happens

Trigger: Calling GetCredentialsAsync (directly or via BitbucketHostProvider.GetCredentialAsync) when GetSupportedAuthenticationModesAsync resolved to AuthenticationModes.None — e.g. an unrecognized host configuration that disables Basic, OAuth, and GCM modes.

Common situations: Custom host provider configurations, settings that disable all auth modes (e.g. both oauth and basic disabled via GCM_* settings), or calling the authentication API directly with modes: AuthenticationModes.None.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/Atlassian.Bitbucket/BitbucketAuthentication.cs:93

            ThrowIfUserInteractionDisabled();

            // If we don't have a desktop session/GUI then we cannot offer OAuth since the only
            // supported grant is authcode (i.e, using a web browser; device code is not supported).
            if (!Context.SessionManager.IsDesktopSession)
            {
                modes = modes & ~AuthenticationModes.OAuth;
            }

            // If the only supported mode is OAuth then just return immediately
            if (modes == AuthenticationModes.OAuth)
            {
                return new CredentialsPromptResult(AuthenticationModes.OAuth);
            }

            // We need at least one mode!
            if (modes == AuthenticationModes.None)
            {
                throw new ArgumentException(@$"Must specify at least one {nameof(AuthenticationModes)}", nameof(modes));
            }

            // Shell out to the UI helper and show the Bitbucket u/p prompt
            if (Context.Settings.IsGuiPromptsEnabled && Context.SessionManager.IsDesktopSession)
            {
                if (TryFindHelperCommand(out string helperCommand, out string args))
                {
                    return await GetCredentialsViaHelperAsync(targetUri, userName, modes, helperCommand, args);
                }

                return await GetCredentialsViaUiAsync(targetUri, userName, modes);
            }

            return await GetCredentialsViaTtyAsync(targetUri, userName, modes);
        }

        private async Task<CredentialsPromptResult> GetCredentialsViaUiAsync(
            Uri targetUri, string userName, AuthenticationModes modes)

View on GitHub (pinned to e8ce762cd0)