jdx/mise · error
receipt target inventory contains an unclassified path
Error message
receipt target inventory contains an unclassified path
What it means
During cask prune validation, mise maps every receipt target path into a set and cross-checks it against the expected 'standard' targets (apps, binaries, fonts, completions). If a target record's path is not in any of those categories, the receipt contains a target the pruner cannot classify, and it bails rather than delete files it cannot attribute safely.
Solutions
- Reinstall the cask via mise (uninstall + install) so the receipt is regenerated with a fully classified target set
- Open the version's receipt file and check which target path is unclassified relative to receipt.apps/binaries/fonts/completions; correct the categorization or remove the stale entry
- Verify receipt.schema_version is 3 and the receipt was written by the current mise; regenerate otherwise
- Exclude that cask token from the prune plan; let brew own the artifact if it installs nonstandard targets
Example fix
// before: receipt targets include an unclassified helper
{"targets": [{"path": "/Applications/Foo.app"}, {"path": "/usr/local/helper"}], "apps": ["/Applications/Foo.app"], ...}
// after: reinstall to regenerate receipt with all targets classified
mise uninstall brew-cask:foo && mise install brew-cask:foo Defensive patterns
Strategy: validation
Validate before calling
// ensure every target path is classified before pruning
fn all_targets_classified(receipt: &CaskReceipt) -> bool {
let expected: BTreeSet<_> = receipt.standard_targets().collect();
receipt.targets.iter().all(|t| expected.contains(&t.path))
}
if !all_targets_classified(&candidate.receipt) { /* skip or reinstall cask */ } Type guard
fn has_only_standard_targets(receipt: &CaskReceipt) -> bool {
let expected: BTreeSet<_> = receipt.standard_targets().collect();
receipt.targets.iter().all(|t| expected.contains(&t.path))
} Try / catch
match apply_cask_prune_plan_in(&plan) {
Ok(removed) => info!("pruned {removed} casks"),
Err(e) if e.to_string().contains("unclassified path") => {
warn!("cask has unclassifiable targets; manage via brew instead: {e:#}");
}
Err(e) => return Err(e),
} Prevention
- Avoid casks that install nonstandard extras if you rely on direct-artifact pruning; prefer brew for those
- Check receipt targets against apps/binaries/fonts/completions before planning a prune
- Regenerate receipts via reinstall after schema or mise version changes
- Treat 'unclassified path' as a signal the cask should be brew-managed, not mise-pruned
When it happens
Trigger: Calling cask_prune_plan_from_tokens or apply_cask_prune_plan_in with a receipt whose targets list includes a path outside standard_targets() — e.g. a target recorded under a category (apps/binaries/fonts/completions) it does not belong to, or an extra target written by a nonstandard install path.
Common situations: A cask that installs extras (pkg payloads, helper tools in unusual locations) recorded in targets but never listed in a category; receipts migrated from an older schema; corrupted or manually modified receipt files.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- artifact target has changed
- receipt target inventory is incomplete or duplicated
- app target is outside an allowed Applications directory
- binary target is not an owned Caskroom symlink
- brew-cask: ' ' must stay below Applications
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/9bc2492d677c045f.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask/state.rs:1061
}
let records = receipt
.targets
.iter()
.map(|record| (record.path.clone(), record))
.collect::<BTreeMap<_, _>>();
let expected = receipt.standard_targets().cloned().collect::<BTreeSet<_>>();
if expected.is_empty()
|| records.len() != receipt.targets.len()
|| records.len() != expected.len()
|| receipt
.metadata_only_apps
.iter()
.any(|path| !receipt.apps.contains(path))
{
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 533346cc37)