From 4ad71920bc720f11106ec8cb8126349b3af0cc8c Mon Sep 17 00:00:00 2001 From: Trang Le Date: Mon, 13 Apr 2026 22:55:59 +0700 Subject: [PATCH] fix: Unable to Run `goose update` on Linux (#8465) --- crates/goose-cli/src/commands/update.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/crates/goose-cli/src/commands/update.rs b/crates/goose-cli/src/commands/update.rs index a513ac52..fb80568c 100644 --- a/crates/goose-cli/src/commands/update.rs +++ b/crates/goose-cli/src/commands/update.rs @@ -462,9 +462,25 @@ fn replace_binary(new_binary: &Path, current_exe: &Path) -> Result<()> { #[cfg(not(target_os = "windows"))] { - // On Unix, copy the new binary over the existing one - fs::copy(new_binary, current_exe) - .with_context(|| format!("Failed to copy new binary to {}", current_exe.display()))?; + let old_exe = current_exe.with_extension("old"); + + // Rename current binary to avoid ETXTBSY on Linux + if current_exe.exists() { + fs::rename(current_exe, &old_exe).with_context(|| { + format!("Failed to rename {} before update", current_exe.display()) + })?; + } + + if let Err(e) = fs::copy(new_binary, current_exe) { + // Restore old binary if copy fails + let _ = fs::rename(&old_exe, current_exe); + return Err(e).with_context(|| { + format!("Failed to copy new binary to {}", current_exe.display()) + }); + } + + // Delete the old backup binary + let _ = fs::remove_file(&old_exe); // Ensure the binary is executable #[cfg(unix)]