jdx/mise · error
brew-cask: refusing to restore flight target through a chang
Error message
brew-cask: refusing to restore flight target through a changed parent: {} What it means
Before restoring a flight backup, validate_backup_parents recomputes the resolved parent directory of both the target and (if present) the backup and compares them with the parents recorded when the backup was taken. A mismatch (parent replaced, moved, or re-symlinked in the meantime) aborts the restore so the original is not written into the wrong location.
Source
Thrown at src/system/packages/brew/cask.rs:3321
fn resolved_parent(path: &Path) -> Result<PathBuf> {
let parent = path
.parent()
.ok_or_else(|| eyre!("brew-cask: flight target has no parent"))?;
Ok(path_with_resolved_existing_ancestor(parent))
}
fn validate_backup_parents(entry: &ArtifactLinkBackup) -> Result<()> {
if resolved_parent(&entry.target)? != entry.target_parent
|| entry
.backup
.as_deref()
.zip(entry.backup_parent.as_ref())
.is_some_and(|(backup, expected)| {
!resolved_parent(backup).is_ok_and(|current| current == *expected)
})
{
bail!(
"brew-cask: refusing to restore flight target through a changed parent: {}",
entry.target.display()
);
}
Ok(())
}
fn flight_backup_parent(target: &Path) -> Result<&Path> {
if let Some(app) = target.ancestors().find(|ancestor| {
ancestor
.extension()
.is_some_and(|extension| extension.eq_ignore_ascii_case("app"))
}) {
return app
.parent()
.ok_or_else(|| eyre!("brew-cask: app flight target has no parent"));
}
targetView on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Restore the original parent directory (recreate it, or move it back) so its resolved path matches the recorded parent, then retry
- Otherwise restore manually: copy the backup file to the intended location and delete the recovery record
- Avoid restructuring directories that contain in-flight cask artifacts
Defensive patterns
Strategy: validation
Validate before calling
use std::fs;
fn backup_parents_unchanged(target: &std::path::Path, backup: Option<&std::path::Path>,
expected_target_parent: &std::path::Path) -> bool {
fs::canonicalize(target.parent().unwrap_or_default())
.is_ok_and(|p| p == expected_target_parent)
&& backup
.map(|b| fs::canonicalize(b.parent().unwrap_or_default()).is_ok())
.unwrap_or(true)
} Try / catch
match recover_flight_backups() {
Err(e) if e.to_string().contains("changed parent") => {
// recreate/move the original parent directory back, then retry recovery
return Err(e.wrap_err("restore the original parent dir, then re-run recovery"));
}
other => other?,
} Prevention
- Do not rename, delete, or re-symlink artifact parent directories between runs
- Re-run recovery promptly after a crash, before reorganizing directories
- Restore the recorded parent layout before manual recovery attempts
When it happens
Trigger: The parent directory of an app/artifact was deleted and recreated, renamed, or had a symlink inserted between the interrupted run and the recovery attempt.
Common situations: User reorganized ~/Applications or the Homebrew prefix between a crashed install and the retry; another installer rebuilt the directory; migration tools moving app containers around.
Related errors
- brew-cask: temporary artifact directory was replaced
- brew-cask: refusing operation through a changed generic arti
- brew-cask: unresolved recovery for {} still preserves its or
- brew-cask: unresolved recovery for newly created target {}
- install from exe
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/f29e20b7baea0ee3.
Report an issue: GitHub.