Hmbown/CodeWhale · error
Refusing to replace managed/system path
Error message
Refusing to replace managed/system path {}.
{GITHUB_MIGRATION_HELP} What it means
Codewhale's self-updater refuses to overwrite a target path that belongs to a package manager or system location (checked via InstallMethod::from_path and protected_update_path). Only the running binary and byte-identical copies of it are safe to replace; command names alone do not establish ownership of a sibling file. The message includes GITHUB_MIGRATION_HELP pointing the user at manual install/uninstall steps.
Solutions
- Uninstall the package-manager copy (brew uninstall / apt remove / cargo uninstall) and reinstall via the official installer script so the binary is self-update-managed.
- Run the updater against the real binary path, not an alias/symlink/wrapper.
- Follow the GITHUB_MIGRATION_HELP printed with the error to migrate installations manually.
- Check where `which -a codewhale` points and remove stale aliases in PATH.
Example fix
// before: self-update over a brew-managed binary fails $ codewhale update // after: let the package manager own updates $ brew upgrade codewhale # or: reinstall via official installer, then `codewhale update`
Defensive patterns
Strategy: validation
Validate before calling
use codewhale_cli::update::InstallMethod;
fn can_self_update(path: &std::path::Path) -> bool {
InstallMethod::from_path(path).supports_self_update()
}
// run before `codewhale update`; if false, update via your package manager instead Prevention
- Install codewhale only via the official installer if you want self-update to work
- Never symlink or alias a package-manager-owned path as the update target
- Run `which -a codewhale` to confirm which copy you are updating
When it happens
Trigger: Running `codewhale update` (run_update) where the resolved update target resolves to a path owned by a package manager (brew, apt, cargo home, etc.), or a path on the protected list; also triggered by tests where an unrelated alias, a desktop-entry primary swap, or a foreign symlink sits in the install directory.
Common situations: User installed via Homebrew/apt/cargo and then runs the built-in updater; a wrapper script or symlink named like the binary exists in PATH; the updater resolves a desktop launcher or alias instead of the real binary.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Refusing to replace : its bytes differ from the running…
- Refusing to replace : the update target is not a regular…
- The package-managed executable was not changed.
- Android identifies runtime linker ` `; refusing to use the…
- Android reported deleted loaded image
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/5c38c5f73b01426a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/update.rs:567
identity.android_proof,
fresh
);
}
}
let bytes = std::fs::read(&identity.path).context("failed to recheck updater binary")?;
if sha256_hex(&bytes) != identity.file_hash {
bail!(
"The running executable path changed during the update; no further files were replaced. Run the intended executable again by its full path."
);
}
Ok(())
}
/// Only the running binary and copies of those exact bytes are ours to update.
/// Command names alone do not establish ownership of an existing sibling.
fn validate_update_target(target: &Path, identity: &UpdateExecutableIdentity) -> Result<()> {
if !InstallMethod::from_path(target).supports_self_update() || protected_update_path(target) {
bail!(
"Refusing to replace managed/system path {}.\n\n{GITHUB_MIGRATION_HELP}",
target.display()
);
}
let metadata = match std::fs::symlink_metadata(target) {
Ok(metadata) => metadata,
Err(error) if error.kind() == std::io::ErrorKind::NotFound && target != identity.path => {
return Ok(());
}
Err(error) => {
return Err(error)
.with_context(|| format!("failed to inspect update target {}", target.display()));
}
};
if !metadata.is_file() || metadata.is_symlink() {
bail!(
"Refusing to replace {}: the update target is not a regular file.\n\n{GITHUB_MIGRATION_HELP}",
target.display()View on GitHub (pinned to 73e0f67d83)