gitbutlerapp/gitbutler · error

directory picker failed (exit {code}): {}

Error message

directory picker failed (exit {code}): {}

What it means

On Linux the but-server directory picker tries zenity or kdialog. Exit code 1 is interpreted as user cancel and returns Ok(None); any other non-zero exit — most commonly 127, command not found — bails with the code and stderr.

Source

Thrown at crates/but-server/src/lib.rs:174

            .output()
            .or_else(|_| {
                std::process::Command::new("kdialog")
                    .args([
                        "--getexistingdirectory",
                        ".",
                        "--title",
                        "Select a Git repository",
                    ])
                    .output()
            })?;
        if !output.status.success() {
            // zenity exits 1 on cancel, kdialog exits 1 on cancel
            let code = output.status.code().unwrap_or(-1);
            if code == 1 {
                return Ok(None);
            }
            let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
            anyhow::bail!(
                "directory picker failed (exit {code}): {}",
                if stderr.is_empty() {
                    "unknown error"
                } else {
                    &stderr
                }
            );
        }
        let path = String::from_utf8_lossy(&output.stdout).trim().to_string();
        if path.is_empty() {
            return Ok(None);
        }
        Ok(Some(path))
    }

    #[cfg(target_os = "windows")]
    {
        // Use the modern IFileOpenDialog via PowerShell (STA is required for

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Install zenity (or kdialog): apt install zenity / dnf install zenity
  2. Ensure the process runs with DISPLAY or WAYLAND_DISPLAY and a DBus session
  3. Check the exit code in the message: 127 means the dialog binary was not found
Defensive patterns

Strategy: fallback

Validate before calling

// Rust: require at least one dialog tool before offering the native picker
let has_dialog = which::which("zenity").is_ok() || which::which("kdialog").is_ok();
offer_picker = has_dialog && std::env::var_os("DISPLAY").is_some() || std::env::var_os("WAYLAND_DISPLAY").is_some();

Try / catch

Exit code 1 already maps to Ok(None) (cancel); for other codes catch the bail — 127 means the dialog binary is missing — and fall back to a manual path input with an 'install zenity' hint.

Prevention

When it happens

Trigger: Running the pick-directory flow on Linux where zenity and kdialog are not installed (exit 127) or fail with codes other than 1, e.g. no DISPLAY/WAYLAND_DISPLAY or a broken desktop environment.

Common situations: Minimal window-manager setups, containers, and servers lacking GTK dialog tools; headless SSH sessions; distros that ship neither zenity nor kdialog by default.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/3fa261e6fab06874. Report an issue: GitHub.