jdx/mise · error
artifact target is now claimed by another cask: {}
Error message
artifact target is now claimed by another cask: {} What it means
validate_cask_prune_claims re-checks, immediately before pruning a mise-managed cask, that none of its recorded artifact targets have been claimed by a different cask since the plan was made. The claims map maps target paths to owning tokens; if some other token now owns a target, pruning would destroy another cask's artifacts, so mise bails naming the path.
Source
Thrown at src/system/packages/brew/cask/state.rs:1021
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(())
}
pub(super) 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 afd2eddd3a)
Solutions
- Re-run the prune operation to regenerate a fresh plan reflecting current ownership
- Identify which cask now claims the path (mise cask state/list or Homebrew metadata) and resolve the overlap (uninstall or update one of them)
- Refresh the cask's ownership receipt (reinstall via mise) so its targets match current claims
Example fix
// before: prune planned while another cask later claimed /usr/local/bin/tool mise cask prune <token> # fails // after: refresh state and re-plan mise reinstall <token> && mise cask prune <token>
Defensive patterns
Strategy: retry
Validate before calling
// after a claim conflict, re-plan instead of forcing // mise revalidates claims itself; the caller should simply re-run planning retry_prune_with_fresh_plan(token);
Try / catch
if let Err(e) = prune(plan) {
if e.to_string().contains("claimed by another cask") {
let plan = build_fresh_plan(token)?;
return prune(plan);
}
return Err(e);
} Prevention
- Apply prune plans immediately after building them
- Avoid concurrent cask installs/prunes that can share target paths
- Refresh ownership receipts (reinstall) after cask changes
When it happens
Trigger: apply_cask_prune_plan_in → validate_cask_prune_claims finds claims.get(&target.path) containing any token other than the candidate's token for one of receipt.targets — a TOCTOU revalidation between plan and apply.
Common situations: Two casks legitimately claiming the same binary/app path after a cask change; another mise or Homebrew operation installed an overlapping cask between planning and pruning; stale receipts listing shared targets.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Homebrew now owns this cask
- metadata-only app ownership cannot be proven safely during p
- Homebrew now owns this cask
- ownership receipt has changed
- brew-cask:{}: Homebrew owns this cask; remove it with Homebr
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/5281b3162d7a5656.
Report an issue: GitHub.