gitbutlerapp/gitbutler · warning · anyhow::Error
Could not determine which forge provider to authenticate wit
Error message
Could not determine which forge provider to authenticate with
What it means
During interactive forge authentication setup, the command opens a terminal picker (prompt_select) over the supported providers (GitHub/GitLab/Bitbucket) and this error fires when the picker returns no selection — i.e. the user cancelled (Esc/Ctrl-C path) or the picker produced zero picks. It is a user-cancellation guard, not a system failure; authentication simply cannot proceed without a provider choice.
Source
Thrown at crates/but/src/command/config.rs:900
}
let auth_options = nonempty::nonempty![
("GitHub", ForgeProvider::GitHub),
("GitLab", ForgeProvider::GitLab),
("Bitbucket", ForgeProvider::Bitbucket)
];
let selected_option = {
let mut input = out
.prepare_for_terminal_input()
.context("Human input required - run this in a terminal")?;
input
.prompt_select(
"Select a forge provider to authenticate with",
&auth_options,
)?
.cloned()
.ok_or_else(|| {
anyhow::anyhow!("Could not determine which forge provider to authenticate with")
})?
};
match selected_option {
ForgeProvider::GitHub => github_auth(out).await,
ForgeProvider::GitLab => gitlab_auth(out).await,
ForgeProvider::Bitbucket => bitbucket_auth(out).await,
}
}
/// Authenticate with Bitbucket Cloud using an Atlassian API token.
async fn bitbucket_auth(out: &mut OutputChannel) -> Result<()> {
use but_bitbucket::AuthStatusResponse;
let t = theme::get();
let mut inout = out
.prepare_for_terminal_input()
.context("Human input required - run this in a terminal")?;View on GitHub (pinned to caf1f223d3)
Solutions
- Simply re-run the command and confirm a pick with Enter instead of Esc.
- If the picker closes instantly, run inside a real TTY (not a piped/non-interactive shell) — the code already fails earlier with 'Human input required' when no terminal is available.
- Check for stray ESC-producing terminal mappings if the picker aborts immediately.
Defensive patterns
Strategy: try-catch
Validate before calling
// Only enter interactive auth when a TTY is attached
if !std::io::stdin().is_terminal() {
eprintln!("forge auth requires an interactive terminal");
return Ok(());
} Try / catch
match run_forge_auth(out).await {
Ok(()) => Ok(()),
Err(e) if e.to_string().contains("Could not determine which forge provider") => {
Ok(()) // user cancelled the picker; treat as no-op, not a crash
}
Err(e) => Err(e),
} Prevention
- Treat picker cancellation as an expected outcome in wrappers and scripts.
- Run forge auth only in a real terminal session.
- Don't wrap the command in tools that swallow the TTY (piped `but` output).
When it happens
Trigger: Running the forge auth command interactively and pressing Esc or aborting the fuzzy-finder picker; a picker session that exits without highlighting+confirming an entry.
Common situations: Users exploring `but config` menus and backing out with Esc; SSH sessions dropped mid-prompt; terminal emulators sending an escape keypress unexpectedly.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Could not determine which accounts to delete
- Could not determine authentication method
- Could not determine selected AI provider
- Could not determine OpenAI credential source
- Could not determine Anthropic credential source
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/8f44ff218419e90a.
Report an issue: GitHub.