gitbutlerapp/gitbutler · error
interactive mode requested, but there is no terminal to…
Error message
interactive mode requested, but there is no terminal to prompt on
What it means
run_installation_impl refuses to run when interactive mode was requested but stdin/stdout is not attached to a TTY, since prompting the user would hang or fail. It is a guard ensuring prompts (and later shell configuration) always have a real terminal.
Solutions
- Run without interactive mode (interactive=false) so defaults are used non-interactively
- Run inside a real terminal (or use `script`/PTY wrapper in CI)
- Remove pipes/redirects on stdin/stdout when invoking the installer
- Pre-configure settings via flags/env so no prompting is needed
Example fix
// before run_installation(config, /* interactive */ true)?; // after let interactive = std::io::stdin().is_terminal(); run_installation(config, interactive)?;
Defensive patterns
Strategy: validation
Validate before calling
let can_prompt = std::io::stdin().is_terminal() && std::io::stdout().is_terminal();
if !can_prompt { /* run non-interactively or abort early */ } Try / catch
match result {
Err(e) if e.to_string().contains("no terminal to prompt on") => {
// fall back to non-interactive mode with defaults
}
other => other?,
} Prevention
- Detect TTY availability before requesting interactive mode
- In CI, always use non-interactive flags
- Avoid piping stdin/stdout when prompts are expected
- Provide config via flags/env to avoid needing prompts
When it happens
Trigger: Calling run_installation/run_installation_with_version with interactive=true from a non-TTY context: CI pipeline, cron job, piped/redirected output, daemon, or embedded invocation.
Common situations: Running the installer in CI (GitHub Actions, Docker build) with an interactive flag set by default, piping installer output to a file or another command, running under a process supervisor without a PTY.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Human input required - run this in a terminal, or specify…
- Interactive setup requires a terminal. Use `but agent setup…
- Shell configuration cannot be performed without a connected…
- Could not determine which forge provider to authenticate…
- No branches selected. Aborting.
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/4765a4199e6e188e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-installer/src/lib.rs:110
/// some of them would dispatch it to an unrelated `but-agent` executable on
/// PATH, whereas `--help` is built in on every version.
fn supports_agent_setup(but_path: &std::path::Path) -> bool {
std::process::Command::new(but_path)
.arg("--help")
.stdin(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.output()
.is_ok_and(|out| {
out.status.success()
&& String::from_utf8_lossy(&out.stdout)
.lines()
.any(|line| line.trim_start().starts_with("agent "))
})
}
fn run_installation_impl(config: InstallerConfig, interactive: bool) -> Result<()> {
if interactive && !ui::is_connected_to_terminal() {
anyhow::bail!("interactive mode requested, but there is no terminal to prompt on");
}
info(&format!("Detected platform: {}", config.platform));
// Fetch release information
let message = match &config.version_request {
VersionRequest::Nightly => "Fetching latest nightly release information...",
VersionRequest::Specific(_) => "Fetching release information...",
VersionRequest::Release => "Fetching latest release information...",
};
info(message);
let release = fetch_release(&config)?;
// Display version information
let channel = match &config.version_request {
VersionRequest::Nightly => {
info(&format!(View on GitHub (pinned to 58e5313667)