{"record":{"id":"0b7ed4b67896d199","repo":"gitbutlerapp/gitbutler","slug":"username-ambiguous-got-accounts-to-delete","errorCode":null,"errorMessage":"Username ambiguous, got {accounts_to_delete:?}","messagePattern":"Username ambiguous, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/command/config.rs","lineNumber":1308,"sourceCode":"        if let Some((username, out)) = username.zip(out.for_human()) {\n            writeln!(out, \"No known forge account matching '{username}'\")?;\n        }\n        return Ok(());\n    }\n\n    // Handle different scenarios based on number of accounts\n    match accounts_to_delete.as_slice() {\n        [single_account] => {\n            // Single account: delete automatically\n            forget_account(single_account)?;\n            if let Some(out) = out.for_human() {\n                writeln!(out, \"Forgot forge account '{single_account}'\")?;\n            }\n        }\n        _ => {\n            // Multiple accounts: prompt user to select\n            let Some(mut input) = out.prepare_for_terminal_input() else {\n                anyhow::bail!(\"Username ambiguous, got {accounts_to_delete:?}\");\n            };\n            let account_options = accounts_to_delete\n                .into_iter()\n                .map(|account| (account.to_string(), account))\n                .collect::<Vec<_>>();\n            let account_options = nonempty::NonEmpty::from_vec(account_options)\n                .context(\"No accounts available to forget\")?;\n\n            let selected_accounts = input\n                .prompt_multi_select(\n                    \"Which of the following accounts do you want to forget?\",\n                    &account_options,\n                )?\n                .ok_or_else(|| anyhow::anyhow!(\"Could not determine which accounts to delete\"))?;\n\n            if selected_accounts.is_empty() {\n                writeln!(input, \"No accounts were selected to forget.\")?;\n                return Ok(());","sourceCodeStart":1290,"sourceCodeEnd":1326,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but/src/command/config.rs#L1290-L1326","documentation":"`but config forge forget` matches the given username against known forge accounts. If the pattern matches multiple accounts, the CLI would normally prompt the user to pick one interactively; but if the output channel cannot provide terminal input (piped stdout, non-TTY, or embedded usage), it cannot disambiguate and bails, printing the ambiguous account list.","triggerScenarios":"Running `but config forge forget <pattern>` where the name/pattern matches two or more stored forge accounts AND stdout is not an interactive terminal (prepare_for_terminal_input returns None), e.g. in scripts or CI.","commonSituations":"Two GitHub accounts stored (work + personal) with a partial-name pattern matching both; running the forget command from a script with redirected output; CI pipelines cleaning up forge credentials.","solutions":["Pass the exact, full username of the single account to forget so the match is unambiguous","Run the command in an interactive terminal so the selection prompt can be shown","List accounts first with `but config forge list-users` to find the exact username"],"exampleFix":"// before\nbut config forge forget john | tee log   # matches john@a and john@b\n// after\nbut config forge forget john@acmecorp","handlingStrategy":"validation","validationCode":"async function resolveUniqueAccount(pattern) {\n  const users = (await exec('but config forge list-users')).stdout.split('\\n').filter(Boolean);\n  const matches = users.filter(u => u.includes(pattern));\n  if (matches.length !== 1) throw new Error(`Pattern matches ${matches.length} accounts: ${matches}`);\n  return matches[0];\n}","typeGuard":"const isUniqueMatch = (matches) => Array.isArray(matches) && matches.length === 1;","tryCatchPattern":"try {\n  await exec(`but config forge forget ${exactUsername}`);\n} catch (e) {\n  if (e.message.includes('Username ambiguous')) {\n    console.error('Pass the exact username; see list-users output in the error');\n  } else throw e;\n}","preventionTips":["Pass full exact usernames, not prefixes, when stdout is not a TTY","Run `but config forge list-users` first to disambiguate","Avoid renaming/colliding account names across forges"],"tags":["cli","configuration","ambiguity"],"backgroundTag":"ambiguous-argument-match","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}