jdx/mise · error · eyre::Report

receipt target inventory contains an unclassified path

Error message

receipt target inventory contains an unclassified path

What it means

Every path in the receipt's targets inventory must be classifiable as an app, binary, font, or completion. This error means a target record exists whose path is in none of those lists — typically flight/generic artifacts or categories this prune implementation does not know how to remove — so the whole cask is refused rather than leaving untracked files behind.

Source

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

        .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!(
                "app target is outside an allowed Applications directory: {}",
                path.display()
            );

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Diff the targets array against the apps/binaries/fonts/completions arrays in .mise-cask.toml and remove the unclassified entry or reinstall the cask
  2. Uninstall the cask via 'mise brew uninstall' (full uninstall path) instead of pruning, since it handles flight/generic artifacts
  3. Upgrade mise so its prune validator understands the artifact category in the receipt
Defensive patterns

Strategy: validation

Validate before calling

// Reject receipts containing target paths outside the classified categories.
fn all_targets_classified(r: &CaskReceipt) -> bool {
    let expected: BTreeSet<&Path> = r.apps.iter()
        .chain(&r.binaries).chain(&r.fonts).chain(&r.completions)
        .map(|p| p.as_path()).collect();
    r.targets.iter().all(|t| expected.contains(t.path.as_path()))
}

Type guard

fn has_unclassified_targets(r: &CaskReceipt) -> bool {
    let expected: std::collections::BTreeSet<&Path> = r.apps.iter()
        .chain(&r.binaries).chain(&r.fonts).chain(&r.completions)
        .map(|p| p.as_path()).collect();
    r.targets.iter().any(|t| !expected.contains(t.path.as_path()))
}

Try / catch

// Catch at plan level and downgrade to a per-cask skip with the token named.
match validate_cask_prune_candidate(&candidate) {
    Ok(()) => candidates.push(candidate),
    Err(reason) => plan.skipped.push(CaskPruneSkip { token: candidate.token, reason: format!("{reason:#}") }),
}

Prevention

When it happens

Trigger: validate_cask_prune_candidate: records.keys().any(|path| !expected.contains(path)). A receipt whose targets include flight_targets or generic_artifact_targets entries (these casks normally carry a prune_blocker and never reach validation), or a receipt from a newer schema with an unknown artifact category.

Common situations: Receipt written by a newer/older mise version with a different artifact taxonomy; hand-added entries to targets; mixing receipts across versions after a downgrade.

Related errors


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