{"record":{"id":"9ef9ca0c635086b0","repo":"git-ecosystem/git-credential-manager","slug":"at-least-one-nameof-authenticationmodes-must-be","errorCode":null,"errorMessage":"At least one {nameof(AuthenticationModes)} must be supplied","messagePattern":"At least one (.+?) must be supplied","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/GitLab/GitLabAuthentication.cs","lineNumber":177,"sourceCode":"                    Context.Console.WriteLine($\"Enter GitLab credentials for '{targetUri}'...\");\n\n                    if (string.IsNullOrWhiteSpace(userName))\n                    {\n                        userName = await TerminalPrompts.CreateText(\"Username\").ShowAsync(Context.Console);\n                    }\n                    else\n                    {\n                        Context.Console.WriteLine($\"Username: {userName}\");\n                    }\n\n                    string token = await TerminalPrompts.CreateSecret(\"Personal access token\").ShowAsync(Context.Console);\n                    return new AuthenticationPromptResult(AuthenticationModes.Pat, new GitCredential(userName, token));\n\n                case AuthenticationModes.Browser:\n                    return new AuthenticationPromptResult(AuthenticationModes.Browser);\n\n                case AuthenticationModes.None:\n                    throw new ArgumentOutOfRangeException(nameof(modes),\n                        @$\"At least one {nameof(AuthenticationModes)} must be supplied\");\n\n                default:\n                    var promptTitle = $\"Select an authentication method for '{targetUri}'\";\n                    var prompt = TerminalPrompts.CreateSelection<AuthenticationModes>()\n                        .Title(promptTitle);\n\n                    if ((modes & AuthenticationModes.Browser) != 0) prompt.AddChoice(\"Web browser\", AuthenticationModes.Browser);\n                    if ((modes & AuthenticationModes.Pat) != 0) prompt.AddChoice(\"Personal access token\", AuthenticationModes.Pat);\n                    if ((modes & AuthenticationModes.Basic) != 0) prompt.AddChoice(\"Username/password\", AuthenticationModes.Basic);\n\n                    AuthenticationModes choice = await prompt.ShowAsync(Context.Console);\n\n                    if (choice == AuthenticationModes.Browser) goto case AuthenticationModes.Browser;\n                    if (choice == AuthenticationModes.Basic) goto case AuthenticationModes.Basic;\n                    if (choice == AuthenticationModes.Pat) goto case AuthenticationModes.Pat;\n\n                    throw new Exception();","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/git-ecosystem/git-credential-manager/blob/e8ce762cd04b4100ae637b5fbf39ef9d0a96561e/src/GitLab/GitLabAuthentication.cs#L159-L195","documentation":"GitLabAuthentication.GetAuthenticationViaTtyAsync handles terminal (TTY) authentication prompts; when handed AuthenticationModes.None it cannot present any prompt and throws ArgumentOutOfRangeException with this message. It is reached from GetAuthenticationAsync when GUI prompts are disabled and the flow falls back to the terminal.","triggerScenarios":"GetAuthenticationAsync falls back to GetAuthenticationViaTtyAsync (no GUI/desktop session or prompts disabled) while the effective modes value is None; also direct calls passing AuthenticationModes.None.","commonSituations":"Headless CI with GCM_INTERACTIVE disabled and gitLabAuthModes restricting to an unavailable mode; misconfiguration leaving no selectable TTY auth mode; programmatic misuse of the API.","solutions":["Configure at least one TTY-compatible auth mode (e.g. Pat) via credential.gitLabAuthModes / GCM_GITLAB_AUTHMODES.","Supply a PAT so the terminal flow can use it without prompting: 'git credential approve' or GCM env credentials.","Do not pass AuthenticationModes.None into the API; compute modes from available capabilities before calling.","Enable GUI prompts (run within a desktop session) if Browser mode is the only intended option."],"exampleFix":"// before (headless CI, no usable mode)\nGCM_GITLAB_AUTHMODES=browser git-credential-manager get\n\n// after\nGCM_GITLAB_AUTHMODES=pat git-credential-manager get  // with a PAT available","handlingStrategy":"validation","validationCode":"if (modes == AuthenticationModes.None)\n{\n    modes = AuthenticationModes.Pat; // ensure a TTY-promptable mode before calling the TTY flow\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    var result = await gitLabAuth.GetAuthenticationAsync(targetUri, userName, modes);\n}\ncatch (ArgumentOutOfRangeException ex) when (ex.ParamName == \"modes\")\n{\n    // recompute modes (at least Pat) and retry\n}","preventionTips":["Configure a TTY-compatible mode (Pat) in credential.gitLabAuthModes for headless runs","Supply a GitLab PAT before disabling interactive prompts","Validate modes != None before invoking authentication","Avoid restricting auth modes to GUI-only options in CI"],"tags":["gitlab","authentication","argument-out-of-range","tty"],"backgroundTag":"argument-out-of-range","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"}