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

  1. Run without interactive mode (interactive=false) so defaults are used non-interactively
  2. Run inside a real terminal (or use `script`/PTY wrapper in CI)
  3. Remove pipes/redirects on stdin/stdout when invoking the installer
  4. 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

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


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)