jdx/mise · error

brew-cask: unresolved recovery for newly created target

Error message

brew-cask: unresolved recovery for newly created target {}

What it means

Same pre-flight scan (ensure_no_unresolved_flight_recovery), but the matching FlightRecoveryRecord has no backup — it was written when the transaction created a brand-new target that must be removed if the operation doesn't commit. An outstanding record means a previous run created this path and died before finishing, so mise refuses to operate on it again until that state is resolved.

Solutions

  1. Re-run the same mise brew command so built-in recovery finishes removing the created target
  2. Or remove the newly created target manually plus its *.recovery record, then retry
  3. Open the record JSON and use its target field to identify exactly which path is pending
  4. Let mise roll back rather than killing it mid-cask-operation

Example fix

# before: stale absent-record
$ mise brew install --cask foo   # refuses: newly created target pending

# after
$ rm "<target-path-from-error>"
$ rm "<state>/brew-cask/flight-recovery/absent-<hash>.recovery"
$ mise brew install --cask foo
Defensive patterns

Strategy: validation

Validate before calling

// Detect pending 'absent' recovery records for a target before install.
fn pending_absent_recovery(target: &Path) -> Option<PathBuf> {
    let dir = state_dir().join("brew-cask/flight-recovery");
    std::fs::read_dir(dir).ok()?.flatten().map(|e| e.path())
        .filter(|p| p.extension().is_some_and(|e| e == "recovery"))
        .find(|p| std::fs::read_to_string(p).ok()
            .and_then(|b| serde_json::from_str::<FlightRecoveryRecord>(&b).ok())
            .is_some_and(|r| r.target == target && r.backup.is_none()))
}

Try / catch

if let Err(e) = install_cask(&cask) {
    if e.to_string().contains("unresolved recovery for newly created target") {
        // remove the created target + its absent-*.recovery record, then retry
    }
}

Prevention

When it happens

Trigger: An interrupted operation that had just created the target file/directory (no prior original existed, hence no backup); the corresponding absent-*.recovery record for it still exists in the flight-recovery directory.

Common situations: Crashed or killed installs leaving newly created files behind; partially written targets blocking every retry of the same cask.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/0e1ee2c46f8fb170. Report an issue: GitHub.

Appendix: source

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

            .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(())
}

fn recover_flight_backups() -> Result<()> {
    let root = flight_recovery_root();
    recover_flight_backups_in(&root)
}

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 6f52dcdf99)