jdx/mise · error
brew-cask: refusing operation through a changed generic arti
Error message
brew-cask: refusing operation through a changed generic artifact parent: {} What it means
Trusted generic-artifact operations open the parent directory by file descriptor and later re-verify (canonicalize) that the opened directory still matches the expected parent path. If the directory was swapped, renamed, or replaced by a symlink between open and use, the operation is aborted — a TOCTOU defense against an attacker replacing the directory mid-operation.
Source
Thrown at src/system/packages/brew/cask/mod.rs:2320
.file_name()
.ok_or_else(|| eyre!("brew-cask: generic artifact target has no filename"))?;
remove_all_at(&parent.fd, name)
}
#[cfg(not(unix))]
{
let _ = expected_parent;
file::remove_all(target)
}
}
#[cfg(unix)]
fn validate_trusted_operation_parent(
parent: &TrustedOperationParent,
expected_parent: &Path,
) -> Result<()> {
let actual_parent = std::fs::canonicalize(parent.path()?)?;
if actual_parent != expected_parent {
bail!(
"brew-cask: refusing operation through a changed generic artifact parent: {}",
expected_parent.display()
);
}
Ok(())
}
fn rename_trusted_generic_target(from: &Path, to: &Path, expected_parent: &Path) -> Result<()> {
#[cfg(unix)]
{
if from.parent() != to.parent() {
bail!("brew-cask: generic artifact backup changed directories");
}
let parent = open_trusted_operation_parent(from, true, false)?;
validate_trusted_operation_parent(&parent, expected_parent)?;
let from_name = from
.file_name()
.ok_or_else(|| eyre!("brew-cask: generic artifact source has no filename"))?;View on GitHub (pinned to afd2eddd3a)
Solutions
- Re-run the install/upgrade command — the race usually does not recur
- Exclude the mise prefix directory from file-sync/AV real-time scanning
- Avoid running concurrent mise operations on the same toolset
Example fix
// before mise install <cask> & mise upgrade <cask> & # concurrent // after mise install <cask> && mise upgrade <cask> # sequential
Defensive patterns
Strategy: retry
Try / catch
match result {
Err(e) if e.to_string().contains("changed generic artifact parent") => {
// transient race: retry once after excluding concurrent writers
eprintln!("directory changed mid-operation; retry without concurrency");
}
Err(e) => return Err(e),
Ok(v) => v,
} Prevention
- Don't run concurrent mise operations on the same toolset
- Exclude the prefix from file-sync (Dropbox/iCloud) and AV scanners
- Retry the install — the race is usually transient
When it happens
Trigger: During backup/restore (rename) or removal of a generic artifact, the directory that was opened via open_trusted_operation_parent no longer canonicalizes to expected_parent (e.g. it was deleted and recreated, or moved by another process).
Common situations: Another mise/Homebrew process concurrently modifying the same cask directory; antivirus or sync tools (Dropbox/iCloud) moving directories during install; a race during parallel upgrades.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- brew-cask: refusing operation through a changed generic arti
- path component {} was concurrently created by another user
- app Info.plist must be a regular file
- brew-cask: invalid {kind} '{value}'
- brew-cask:{}: cask metadata has no sha256
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/50cef086880caff2.
Report an issue: GitHub.