jdx/mise · error · eyre::Report
artifact target is now claimed by another cask: {}
Error message
artifact target is now claimed by another cask: {} What it means
Before pruning a cask's artifacts, mise builds a claim map of every artifact target path from the receipts of all known casks (Homebrew-owned and mise-owned). If any target of the prune candidate is claimed by a receipt belonging to a different cask token, it bails — deleting would destroy the other cask's artifact. This is an ownership guard, not a filesystem error.
Source
Thrown at src/system/packages/brew/cask.rs:6995
let version = version?;
if !version.file_type()?.is_dir()
|| version.file_name().to_string_lossy().starts_with('.')
{
continue;
}
if let Some(receipt) = read_receipt(&version.path())? {
for target in receipt.targets {
claims.entry(target.path).or_default().insert(token.clone());
}
}
}
}
for target in &candidate.receipt.targets {
if claims
.get(&target.path)
.is_some_and(|tokens| tokens.iter().any(|token| token != &candidate.token))
{
bail!(
"artifact target is now claimed by another cask: {}",
target.path.display()
);
}
}
Ok(())
}
fn validate_cask_prune_candidate(candidate: &CaskPruneCandidate) -> Result<()> {
if homebrew_metadata_present(&candidate.token) {
bail!("Homebrew now owns this cask");
}
let receipt = &candidate.receipt;
if read_receipt(&candidate.version_dir)?.as_ref() != Some(receipt) {
bail!("ownership receipt has changed");
}
if receipt.schema_version != 3 || !receipt.prune_safe || !receipt.pkg_ids.is_empty() {
bail!("receipt is not marked safe for direct-artifact pruning");View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Prefer `brew uninstall --cask <token>` for the cask you want removed — Homebrew resolves shared artifacts itself
- Inspect receipts to see who claims the path: look under the caskroom metadata/receipt dirs for both tokens before pruning
- Remove the stale receipt of the cask you no longer have, so its false claim disappears, then retry the prune
- Keep both casks if they genuinely share the artifact
Defensive patterns
Strategy: validation
Validate before calling
// Before pruning, confirm no other cask receipt claims the same targets:
fn target_unclaimed(target: &std::path::Path, claims: &std::collections::HashMap<std::path::PathBuf, std::collections::BTreeSet<String>>, my_token: &str) -> bool {
claims
.get(target)
.map(|tokens| tokens.iter().all(|t| t == my_token))
.unwrap_or(true)
} Try / catch
match validate_prune_targets(&candidate) {
Ok(()) => prune(),
Err(e) if e.to_string().contains("claimed by another cask") => {
warn!("artifact shared with another cask; deferring to brew uninstall");
Ok(())
}
Err(e) => Err(e),
} Prevention
- Use brew uninstall --cask for removals when Homebrew may also track the cask
- Avoid manually copying .app bundles between cask-managed locations — receipts keep claiming the original path
- Clean up stale receipts for casks you removed by hand before running prune
When it happens
Trigger: Two casks' receipts record the same target path (shared bundle name, nested .app inside another cask's bundle, or a moved receipt), and one of them is being pruned/uninstalled via mise.
Common situations: Casks that install sub-apps into another cask's bundle directory; a cask reinstalled under a different token or renamed upstream; stale receipts from manually copied .app bundles.
Related errors
- Homebrew now owns this cask
- brew-cask is not available: {}
- brew-cask prune is not supported on windows
- brew-cask: refusing operation through untrusted directory {}
- brew-cask: staging directory is not owned by the current use
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/739397d4f50bf4cf.
Report an issue: GitHub.