jdx/mise · error
brew-cask: unresolved recovery for newly created target {}
Error message
brew-cask: unresolved recovery for newly created target {} What it means
Companion to the backup-case recovery error: when a flight transaction created a target that didn't exist before, the recovery record has no backup. If such a record still exists for this target, a previous run crashed after creating the target but before committing, and mise refuses to touch the target to avoid destroying a possibly-user-created file. The stale target must be resolved (recovered or removed) first.
Source
Thrown at src/system/packages/brew/cask/flight.rs:398
.is_none_or(|extension| extension != "recovery")
{
continue;
}
let Ok(body) = file::read_to_string(&path) else {
continue;
};
let Ok(record) = serde_json::from_str::<FlightRecoveryRecord>(&body) else {
continue;
};
if record.target == target {
if let Some(backup) = record.backup {
bail!(
"brew-cask: unresolved recovery for {} still preserves its original at {}",
target.display(),
backup.display()
);
}
bail!(
"brew-cask: unresolved recovery for newly created target {}",
target.display()
);
}
}
Ok(())
}
pub(super) fn recover_flight_backups() -> Result<()> {
let root = flight_recovery_root();
recover_flight_backups_in(&root)
}
pub(super) fn recover_flight_backups_in(root: &Path) -> Result<()> {
let Ok(entries) = std::fs::read_dir(root) else {
return Ok(());
};
for entry in entries {View on GitHub (pinned to afd2eddd3a)
Solutions
- Re-run the install so recover_flight_backups can evaluate the target (via receipt claim) and clear the record.
- If the target is a leftover from the crashed run and you don't need it, delete it manually, then remove the corresponding absent-*.recovery file in mise's brew-cask/flight-recovery state dir.
- If the target is user data you created, keep it and remove the stale recovery record after confirming no install is in progress.
- Avoid running two mise cask operations on the same app simultaneously.
Defensive patterns
Strategy: try-catch
Try / catch
// resolve the stale 'newly created' target before reinstalling
match install_cask(token) {
Err(e) if e.to_string().contains("unresolved recovery for newly created target") => {
// inspect the target path in the message; delete if it is a crash leftover,
// then remove the absent-*.recovery record and retry
retry(install_cask(token))
}
other => other,
} Prevention
- Let interrupted installs complete recovery on the next run before starting new ones.
- Check mise state (brew-cask/flight-recovery) for stale records after a crash.
- Serialize cask operations that touch the same /Applications target.
When it happens
Trigger: protect_with_elevation → ensure_no_unresolved_flight_recovery finds a *.recovery record whose target matches and whose backup field is None (an 'absent-*' record) — a prior run died between creating the new target and finishing the transaction.
Common situations: Interrupted first-time install of a cask app (no previous version to back up); a crashed run left the newly linked app in place; concurrent mise runs racing on the same app target.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- brew-cask: unresolved recovery for {} still preserves its or
- brew-cask: unresolved recovery for {} still preserves its or
- brew-cask: unresolved recovery for newly created target {}
- interrupted file recovery needs attention; temporary recover
- brew-cask: refusing to restore flight target through a chang
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/c87cbfe453d099e4.
Report an issue: GitHub.