jdx/mise · error · eyre::Report

receipt target inventory is incomplete or duplicated

Error message

receipt target inventory is incomplete or duplicated

What it means

Before pruning, the receipt's targets list is cross-checked against the union of its classified artifact lists (apps + binaries + fonts + completions). The error fires when that expected set is empty, when the path->record map is smaller than targets (duplicate paths collapsed by the BTreeMap), or when the counts disagree — i.e. the receipt is internally inconsistent and cannot be trusted to describe what is safe to delete.

Source

Thrown at src/system/packages/brew/cask.rs:7032

    }
    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()
    {
        bail!("receipt target inventory is incomplete or duplicated");
    }
    if records.keys().any(|path| !expected.contains(path)) {
        bail!("receipt target inventory contains an unclassified path");
    }

    for path in &receipt.apps {
        let record = records
            .get(path)
            .ok_or_else(|| eyre!("missing app target record"))?;
        if record.fingerprint.kind != CaskTargetKind::Directory
            || !allowed_appdir_roots()?
                .iter()
                .any(|root| path_is_below(path, root))
            || !path.file_name().is_some_and(|name| {
                staged_app_matches_target(record, &candidate.version_dir.join(name))
            })
        {
            bail!(

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Read Caskroom/<token>/<version>/.mise-cask.toml and verify every path in [[targets]] also appears in apps/binaries/fonts/completions exactly once with no duplicates
  2. Reinstall the cask to let write_receipt_with_flight_targets regenerate a consistent receipt
  3. If the file is corrupted beyond repair, uninstall and reinstall the cask, or delete the version directory manually after verifying no symlinks point into it
Defensive patterns

Strategy: validation

Validate before calling

// Verify a receipt is internally consistent before handing it to prune.
use std::collections::{BTreeMap, BTreeSet};
fn inventory_consistent(r: &CaskReceipt) -> bool {
    let records: BTreeMap<&Path, _> = r.targets.iter().map(|t| (t.path.as_path(), t)).collect();
    let expected: BTreeSet<&Path> = r.apps.iter()
        .chain(&r.binaries).chain(&r.fonts).chain(&r.completions)
        .map(|p| p.as_path()).collect();
    !expected.is_empty()
        && records.len() == r.targets.len()
        && records.len() == expected.len()
}

Type guard

fn receipt_inventory_ok(r: &CaskReceipt) -> bool {
    let dup = r.targets.len() != r.targets.iter().map(|t| &t.path).collect::<std::collections::BTreeSet<_>>().len();
    !dup && !r.apps.is_empty() || !r.binaries.is_empty() || !r.fonts.is_empty() || !r.completions.is_empty()
}

Try / catch

if let Err(reason) = validate_cask_prune_candidate(&candidate) {
    plan.skipped.push(CaskPruneSkip { token, reason: format!("recorded artifacts cannot be removed safely: {reason:#}") });
    continue;
}

Prevention

When it happens

Trigger: validate_cask_prune_candidate: expected.is_empty() || records.len() != receipt.targets.len() || records.len() != expected.len(). Produced by a .mise-cask.toml with the same path listed twice in targets, targets missing entries that apps/binaries/fonts/completions reference (or vice versa), or an all-empty receipt.

Common situations: Hand-edited or merge-conflicted receipt file; receipt truncated by a crash mid-write; a bug or incompatible version writing inconsistent receipts; disk corruption.

Related errors


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