jdx/mise · error · eyre::Report
receipt is not marked safe for direct-artifact pruning
Error message
receipt is not marked safe for direct-artifact pruning
What it means
The direct-artifact prune path only deletes artifacts for receipts it fully understands: schema_version must be 3, prune_safe must be true, and pkg_ids must be empty. Receipts written by older versions (schema 1/2), receipts with a prune_blocker (casks with uninstall scripts, suite/pkg behavior), and casks that installed macOS installer packages are refused because removal requires logic beyond deleting recorded files and symlinks.
Source
Thrown at src/system/packages/brew/cask.rs:7013
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");
}
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)
.cloned()
.collect::<BTreeSet<_>>();
if expected.is_empty()
|| records.len() != receipt.targets.len()
|| records.len() != expected.len()
{View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Reinstall the affected cask with the current mise version so write_receipt_with_flight_targets emits a schema-3 receipt (schema_version: 3, prune_safe set honestly)
- Check the receipt's prune_blocker field in Caskroom/<token>/<version>/.mise-cask.toml — if set, uninstall via 'mise brew uninstall' instead of pruning
- For pkg-based casks (pkg_ids non-empty), remove the packages via macOS (pkgutil) or keep them managed by Homebrew proper
Example fix
# before: receipt shows schema 1 / prune blocker cat "$(mise brew prefix)/Caskroom/some-cask/1.0/.mise-cask.toml" # schema_version = 1 # after: reinstall to regenerate a current receipt mise brew install --force some-cask mise system prune
Defensive patterns
Strategy: validation
Validate before calling
// Only offer a receipt to the prune path when it is schema 3, prune-safe,
// and pkg-free — mirror the checks before planning.
fn prune_eligible(receipt: &CaskReceipt) -> bool {
receipt.schema_version == 3 && receipt.prune_safe && receipt.pkg_ids.is_empty()
} Type guard
fn is_schema3_prune_safe(r: &CaskReceipt) -> bool {
r.schema_version == 3 && r.prune_safe && r.pkg_ids.is_empty()
} Try / catch
// Plan-phase pattern: pre-check and record a friendly skip reason instead of
// letting the hard bail surface during apply.
if receipt.schema_version != 3 || !receipt.prune_safe || !receipt.pkg_ids.is_empty() {
plan.skipped.push(CaskPruneSkip { token, reason: "receipt predates safe prune metadata; upgrade or reinstall first".into() });
continue;
} Prevention
- Reinstall casks after upgrading mise so receipts carry schema 3 + prune metadata
- Prefer explicit 'mise brew uninstall' for pkg-based or scripted casks; pruning is only for direct-artifact casks
- Check receipt.prune_blocker before expecting a prune to proceed
When it happens
Trigger: validate_cask_prune_candidate after the receipt equality check: receipt.schema_version != 3, !receipt.prune_safe, or receipt.pkg_ids non-empty. Reachable when a hand-crafted candidate skips the plan-phase pre-checks (cask.rs:6832/6840 normally skip these with friendlier reasons), e.g. calling apply with a plan from a mixed-version install.
Common situations: Cask installed by an older mise whose receipts predate prune metadata; cask definition includes pkg installer artifacts (e.g. drivers, system tools); cask has uninstall lifecycle actions that mise refuses to run; upgrading mise but not reinstalling the cask.
Related errors
- ownership receipt has changed
- receipt target inventory is incomplete or duplicated
- receipt target inventory contains an unclassified path
- app target is outside an allowed Applications directory: {}
- binary target is not an owned Caskroom symlink: {}
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/41706689894cd659.
Report an issue: GitHub.