{"record":{"id":"3fa261e6fab06874","repo":"gitbutlerapp/gitbutler","slug":"directory-picker-failed-exit-code","errorCode":null,"errorMessage":"directory picker failed (exit {code}): {}","messagePattern":"directory picker failed \\(exit (.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-server/src/lib.rs","lineNumber":174,"sourceCode":"            .output()\n            .or_else(|_| {\n                std::process::Command::new(\"kdialog\")\n                    .args([\n                        \"--getexistingdirectory\",\n                        \".\",\n                        \"--title\",\n                        \"Select a Git repository\",\n                    ])\n                    .output()\n            })?;\n        if !output.status.success() {\n            // zenity exits 1 on cancel, kdialog exits 1 on cancel\n            let code = output.status.code().unwrap_or(-1);\n            if code == 1 {\n                return Ok(None);\n            }\n            let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();\n            anyhow::bail!(\n                \"directory picker failed (exit {code}): {}\",\n                if stderr.is_empty() {\n                    \"unknown error\"\n                } else {\n                    &stderr\n                }\n            );\n        }\n        let path = String::from_utf8_lossy(&output.stdout).trim().to_string();\n        if path.is_empty() {\n            return Ok(None);\n        }\n        Ok(Some(path))\n    }\n\n    #[cfg(target_os = \"windows\")]\n    {\n        // Use the modern IFileOpenDialog via PowerShell (STA is required for","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-server/src/lib.rs#L156-L192","documentation":"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.","triggerScenarios":"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.","commonSituations":"Minimal window-manager setups, containers, and servers lacking GTK dialog tools; headless SSH sessions; distros that ship neither zenity nor kdialog by default.","solutions":["Install zenity (or kdialog): apt install zenity / dnf install zenity","Ensure the process runs with DISPLAY or WAYLAND_DISPLAY and a DBus session","Check the exit code in the message: 127 means the dialog binary was not found"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Rust: require at least one dialog tool before offering the native picker\nlet has_dialog = which::which(\"zenity\").is_ok() || which::which(\"kdialog\").is_ok();\noffer_picker = has_dialog && std::env::var_os(\"DISPLAY\").is_some() || std::env::var_os(\"WAYLAND_DISPLAY\").is_some();","typeGuard":null,"tryCatchPattern":"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.","preventionTips":["Declare zenity/kdialog as dependencies or check for them before showing the picker","Run pickers only with DISPLAY/WAYLAND_DISPLAY and a DBus session set"],"tags":["linux","zenity","kdialog","directory-picker","native-dialog"],"backgroundTag":"native-dialog-failed","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}