jdx/mise · warning · eyre::Report
ownership receipt has changed
Error message
ownership receipt has changed
What it means
The prune validator re-reads the `.mise-cask.toml` receipt from the cask's Caskroom version directory and compares it against the receipt captured when the prune candidate was built (read_receipt(...) != candidate.receipt). If they differ, ownership may have changed hands between planning and execution, so pruning is refused rather than deleting artifacts installed by a different invocation.
Solutions
- Re-run the prune after the concurrent install/upgrade finishes; the plan is rebuilt from the fresh receipt.
- Avoid running multiple mise operations that touch the same Caskroom simultaneously; do not hand-edit `.mise-cask.toml`.
- If the receipt is corrupted, reinstall the cask with mise so a consistent receipt is written, then prune.
- Clean up leftover `.mise-tmp-*` directories from an interrupted operation and retry.
Defensive patterns
Strategy: validation
Validate before calling
// Re-read and compare the receipt immediately before acting on a prune candidate
let current = read_receipt(&candidate.version_dir)?;
if current.as_ref() != Some(&candidate.receipt) {
// someone reinstalled/rewrote the cask; rebuild the plan instead of pruning
} Try / catch
Catch the Err from validate_cask_prune_candidate and push the candidate to the skipped list with the reason, then optionally re-plan; never delete artifacts when ownership is unverifiable.
Prevention
- Run one mise operation that mutates the Caskroom at a time.
- Never hand-edit .mise-cask.toml receipts.
- After an interrupted install/upgrade, re-run it to completion before pruning.
When it happens
Trigger: The `.mise-cask.toml` inside `<Caskroom>/<token>/<version>/` is rewritten between candidate discovery and validation — a concurrent mise install/upgrade of the same cask, another process touching the receipt, or a corrupted receipt that now parses to a different value.
Common situations: Two mise processes running at once (install in one terminal, prune in another); CI or shell hooks racing interactive use; hand-edited or half-written receipts after a crash.
Related errors
- metadata-only app ownership cannot be proven safely during…
- receipt is not marked safe for direct-artifact pruning
- receipt target inventory contains an unclassified path
- receipt target inventory is incomplete or duplicated
- app target is outside an allowed Applications directory
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/1eecc5b4e97b53a5.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask.rs:7254
.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");
}
if !receipt.metadata_only_apps.is_empty() {
bail!("metadata-only app ownership cannot be proven safely during pruning");
}
let records = receipt
.targets
.iter()
.map(|record| (record.path.clone(), record))
.collect::<BTreeMap<_, _>>();
let expected = receipt
.apps
.iter()
.chain(&receipt.binaries)
.chain(&receipt.fonts)
.chain(&receipt.completions)View on GitHub (pinned to 6f52dcdf99)