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

  1. 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)
  2. Check the receipt's prune_blocker field in Caskroom/<token>/<version>/.mise-cask.toml — if set, uninstall via 'mise brew uninstall' instead of pruning
  3. 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

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


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/41706689894cd659. Report an issue: GitHub.