{"record":{"id":"e64f7fdc3371c4e8","repo":"git-ecosystem/git-credential-manager","slug":"must-specify-at-least-one-nameof-authenticationmo","errorCode":null,"errorMessage":"Must specify at least one {nameof(AuthenticationModes)}","messagePattern":"Must specify at least one (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/GitLab/GitLabAuthentication.cs","lineNumber":72,"sourceCode":"    }\n\n    public class GitLabAuthentication : AuthenticationBase, IGitLabAuthentication\n    {\n        public GitLabAuthentication(ICommandContext context)\n            : base(context) { }\n\n        public async Task<AuthenticationPromptResult> GetAuthenticationAsync(Uri targetUri, string userName, AuthenticationModes modes)\n        {\n            // If we cannot start a browser then don't offer the option\n            if (!Context.SessionManager.IsWebBrowserAvailable)\n            {\n                modes = modes & ~AuthenticationModes.Browser;\n            }\n\n            // We need at least one mode!\n            if (modes == AuthenticationModes.None)\n            {\n                throw new ArgumentException(@$\"Must specify at least one {nameof(AuthenticationModes)}\", nameof(modes));\n            }\n\n            ThrowIfUserInteractionDisabled();\n\n            if (Context.Settings.IsGuiPromptsEnabled && Context.SessionManager.IsDesktopSession)\n            {\n                if (TryFindHelperCommand(out string helperCommand, out string args))\n                {\n                    return await GetAuthenticationViaHelperAsync(targetUri, userName, modes, helperCommand, args);\n                }\n\n                return await GetAuthenticationViaUiAsync(targetUri, userName, modes);\n            }\n\n            return await GetAuthenticationViaTtyAsync(targetUri, userName, modes);\n        }\n\n        private async Task<AuthenticationPromptResult> GetAuthenticationViaUiAsync(","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/git-ecosystem/git-credential-manager/blob/e8ce762cd04b4100ae637b5fbf39ef9d0a96561e/src/GitLab/GitLabAuthentication.cs#L54-L90","documentation":"GitLabAuthentication.GetAuthenticationAsync reduces the requested AuthenticationModes (removing unavailable modes like Browser when no desktop session exists) and if nothing remains (modes == AuthenticationModes.None) throws ArgumentException because there is no viable authentication method for the GitLab host.","triggerScenarios":"Calling GetAuthenticationAsync with AuthenticationModes.None, or with modes that all get stripped (e.g. only Browser requested in a headless session, or PAT disabled by config) leaving None.","commonSituations":"Configuring credential.gitLabAuthModes to a single mode that is unavailable in the environment (Browser on a server without a desktop session); passing None programmatically; GCM detecting no desktop session so interactive modes are removed.","solutions":["Set credential.gitLabAuthModes (or GCM_GITLAB_AUTHMODES env var) to include an available mode such as Pat (comma-separated list of Browser, Pat, etc.).","Do not pass AuthenticationModes.None when calling the API programmatically.","Run in an environment with a desktop session if you rely on Browser mode.","Provide a PAT so interactive modes can be bypassed entirely (GCM_INTERACTIVE=Never plus stored credential)."],"exampleFix":"// before\ngit config --global credential.gitLabAuthModes browser   // headless: mode stripped -> None\n\n// after\ngit config --global credential.gitLabAuthModes pat,browser","handlingStrategy":"validation","validationCode":"var raw = Environment.GetEnvironmentVariable(\"GCM_GITLAB_AUTHMODES\")\n           ?? config[\"credential.gitLabAuthModes\"];\nvar modes = ParseModes(raw); // parse comma-separated Browser,Pat,...\nif (modes == AuthenticationModes.None)\n{\n    modes = AuthenticationModes.Pat; // ensure at least one viable mode\n}\nif (!hasDesktopSession) modes &= ~AuthenticationModes.Browser;\nif (modes == AuthenticationModes.None) throw new InvalidOperationException(\"No viable GitLab auth mode configured\");","typeGuard":null,"tryCatchPattern":"try\n{\n    var result = await gitLabAuth.GetAuthenticationAsync(targetUri, userName, modes);\n}\ncatch (ArgumentException ex) when (ex.ParamName == \"modes\")\n{\n    // retry with a default mode set including Pat\n}","preventionTips":["Always include Pat in credential.gitLabAuthModes for headless environments","Never pass AuthenticationModes.None programmatically","Verify Browser mode availability (desktop session) before relying on it","Store a GitLab PAT so interactive modes are optional"],"tags":["gitlab","authentication","argument-validation","configuration"],"backgroundTag":"invalid-argument-value","analyzedSha":"e8ce762cd04b4100ae637b5fbf39ef9d0a96561e","analyzedAt":"2026-09-11T17:15:08.753Z","contentChangedAt":"2026-09-11T17:15:08.753Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}