NousResearch/hermes-agent · error · anyhow::Error
installing updated app at {}: {err}
Error message
installing updated app at {}: {err} What it means
Second phase of swap_in_new_bundle: the staged tmp bundle could not be renamed onto the target path. The updater then restores the original from the .hermes-update-old backup (best-effort), cleans up tmp, and errors — preserving the invariant that the target always points at a working bundle, either rolled back or untouched.
Source
Thrown at apps/bootstrap-installer/src-tauri/src/update.rs:1100
// bail — a failed update must not brick the install.
remove_dir_if_exists(tmp).await;
return Err(anyhow!(
"could not move existing app aside at {} (leaving it in place): {err}",
target.display()
));
}
true
} else {
false
};
if let Err(err) = tokio::fs::rename(tmp, target).await {
// Restore the original app from the backup so the user keeps a working
// install, and clean up the staged copy.
if moved_old {
let _ = tokio::fs::rename(old, target).await;
}
remove_dir_if_exists(tmp).await;
return Err(anyhow!("installing updated app at {}: {err}", target.display()));
}
remove_dir_if_exists(old).await;
Ok(())
}
#[cfg(not(target_os = "macos"))]
async fn install_macos_app_update(
_app: &AppHandle,
_install_root: &Path,
target_app: &Path,
) -> Result<PathBuf> {
Ok(target_app.to_path_buf())
}
async fn remove_dir_if_exists(path: &Path) {
if path.exists() {
let _ = tokio::fs::remove_dir_all(path).await;
}View on GitHub (pinned to c896c09c42)
Solutions
- Free space on the target volume and retry — rollback has already restored the old app, so the install is safe.
- Ensure no other update/process is touching the target path (see the update-lock error [545]).
- Keep HERMES_HOME and the target .app on the same volume so the swap renames stay same-filesystem.
- If the old app was not restored (moved_old was false), re-run the installer to lay down a fresh app.
Defensive patterns
Strategy: fallback
Validate before calling
// Ensure tmp and target are on the same filesystem so the final rename is atomic.
fn same_volume(a: &std::path::Path, b: &std::path::Path) -> bool {
match (std::fs::metadata(a), std::fs::metadata(b)) {
(Ok(ma), Ok(mb)) => ma.dev() == mb.dev(),
_ => false,
}
}
// std::os::unix::fs::MetadataExt for dev(); stage tmp next to target, which the code already does. Try / catch
// Already correct: roll the original back from `old` before erroring, and clean tmp.
if let Err(err) = tokio::fs::rename(tmp, target).await {
if moved_old {
let _ = tokio::fs::rename(old, target).await; // restore working bundle
}
remove_dir_if_exists(tmp).await;
return Err(anyhow!("installing updated app at {}: {err} (original restored)", target.display()));
} Prevention
- Free target-volume disk space before updating — the swap needs headroom for the rename.
- Guarantee single-flight updates (see [545]) so nothing recreates the target path mid-swap.
- Keep HERMES_HOME and the installed .app on the same volume.
When it happens
Trigger: Disk full so the rename cannot complete; target path recreated by another process between the two renames (losing the exclusive slot); cross-device rename (tmp staged on a different volume than target); SIP/permissions blocking writes to the final path.
Common situations: Target volume ran out of space mid-update; a second updater instance raced the swap; tmp and target on different mounts (e.g. target in /Applications on the system disk while HERMES_HOME staging sits on an external volume).
Related errors
- could not move existing app aside at {} (leaving it in place
- desktop rebuild succeeded but no Hermes.app was found under
- ditto failed while copying updated app into {}
- Could not find the hermes CLI under {}. Is Hermes installed?
- refusing to install update into non-app path: {}
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/088fb38d5667ad79.
Report an issue: GitHub.