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
- Check the modes argument passed to GetCredentialsAsync; ensure at least one AuthenticationModes flag (Basic, OAuth, Browser, Gcm) is set
- Inspect the settings controlling GetSupportedAuthenticationModesAsync (e.g. GCM_BITBUCKET_AUTHMODES / host provider config) and enable a valid mode
- 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
- Never pass AuthenticationModes.None to credential APIs
- Derive modes from the host provider's GetSupportedAuthenticationModesAsync, not hard-coded values
- Add a unit test asserting non-None modes for each host config
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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- At least one AuthenticationModes must be supplied
- User cancelled credential prompt
- Argument cannot be empty or white space.
- Argument must be an absolute URI.
- Argument must be positive or zero (non-negative).
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)