{"record":{"id":"138aef5dec35f4c2","repo":"jdx/mise","slug":"receipt-target-inventory-contains-an-unclassified","errorCode":null,"errorMessage":"receipt target inventory contains an unclassified path","messagePattern":"receipt target inventory contains an unclassified path","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask.rs","lineNumber":7035,"sourceCode":"        .iter()\n        .map(|record| (record.path.clone(), record))\n        .collect::<BTreeMap<_, _>>();\n    let expected = receipt\n        .apps\n        .iter()\n        .chain(&receipt.binaries)\n        .chain(&receipt.fonts)\n        .chain(&receipt.completions)\n        .cloned()\n        .collect::<BTreeSet<_>>();\n    if expected.is_empty()\n        || records.len() != receipt.targets.len()\n        || records.len() != expected.len()\n    {\n        bail!(\"receipt target inventory is incomplete or duplicated\");\n    }\n    if records.keys().any(|path| !expected.contains(path)) {\n        bail!(\"receipt target inventory contains an unclassified path\");\n    }\n\n    for path in &receipt.apps {\n        let record = records\n            .get(path)\n            .ok_or_else(|| eyre!(\"missing app target record\"))?;\n        if record.fingerprint.kind != CaskTargetKind::Directory\n            || !allowed_appdir_roots()?\n                .iter()\n                .any(|root| path_is_below(path, root))\n            || !path.file_name().is_some_and(|name| {\n                staged_app_matches_target(record, &candidate.version_dir.join(name))\n            })\n        {\n            bail!(\n                \"app target is outside an allowed Applications directory: {}\",\n                path.display()\n            );","sourceCodeStart":7017,"sourceCodeEnd":7053,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/packages/brew/cask.rs#L7017-L7053","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Diff the targets array against the apps/binaries/fonts/completions arrays in .mise-cask.toml and remove the unclassified entry or reinstall the cask","Uninstall the cask via 'mise brew uninstall' (full uninstall path) instead of pruning, since it handles flight/generic artifacts","Upgrade mise so its prune validator understands the artifact category in the receipt"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Reject receipts containing target paths outside the classified categories.\nfn all_targets_classified(r: &CaskReceipt) -> bool {\n    let expected: BTreeSet<&Path> = r.apps.iter()\n        .chain(&r.binaries).chain(&r.fonts).chain(&r.completions)\n        .map(|p| p.as_path()).collect();\n    r.targets.iter().all(|t| expected.contains(t.path.as_path()))\n}","typeGuard":"fn has_unclassified_targets(r: &CaskReceipt) -> bool {\n    let expected: std::collections::BTreeSet<&Path> = r.apps.iter()\n        .chain(&r.binaries).chain(&r.fonts).chain(&r.completions)\n        .map(|p| p.as_path()).collect();\n    r.targets.iter().any(|t| !expected.contains(t.path.as_path()))\n}","tryCatchPattern":"// Catch at plan level and downgrade to a per-cask skip with the token named.\nmatch validate_cask_prune_candidate(&candidate) {\n    Ok(()) => candidates.push(candidate),\n    Err(reason) => plan.skipped.push(CaskPruneSkip { token: candidate.token, reason: format!(\"{reason:#}\") }),\n}","preventionTips":["Use the full uninstall path for casks with flight/generic artifacts; prune only covers apps/binaries/fonts/completions","Reinstall casks when upgrading or downgrading mise so the receipt taxonomy matches the tool"],"tags":["brew","cask","prune","receipt","inventory"],"backgroundTag":"manifest-validation-failed","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}