jdx/mise · error

brew-cask: internal non-terminate flight step

Error message

brew-cask: internal non-terminate flight step

What it means

Internal invariant violation: execute_terminate_process was invoked with a FlightStep that is not FlightStep::TerminateProcess. This function destructures the step to read the terminate-process parameters; any other variant means a caller bug in dispatching flight steps.

Source

Thrown at src/system/packages/brew/cask/flight.rs:873

pub(super) fn execute_terminate_process(
    step: &FlightStep,
    staged_path: &Path,
    appdir: &Path,
    version: &str,
    mut run: impl FnMut(&Path, &[String], bool) -> Result<()>,
    mut sleep: impl FnMut(std::time::Duration),
) -> Result<()> {
    let FlightStep::TerminateProcess {
        name,
        match_mode,
        sudo,
        attempts,
        must_succeed,
        notices,
        failure_message,
    } = step
    else {
        bail!("brew-cask: internal non-terminate flight step");
    };
    let expand = |value: &str| expand_cask_template(value, staged_path, appdir, Some(version));
    for notice in notices {
        miseprintln!("{}", expand(notice));
    }
    let name = expand(name);
    let (command, args) = match *match_mode {
        ProcessMatch::Name => (Path::new("/usr/bin/killall"), vec![name]),
        ProcessMatch::Full => (Path::new("/usr/bin/pkill"), vec!["-f".to_string(), name]),
    };
    let mut last_error = None;
    for attempt in 0..*attempts {
        match run(command, &args, *sudo) {
            Ok(()) => return Ok(()),
            Err(err) => last_error = Some(err),
        }
        if attempt + 1 < *attempts {
            sleep(std::time::Duration::from_secs(1));

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Route all flight steps through execute_flight_step, which dispatches on the variant.
  2. Fix the caller to match only FlightStep::TerminateProcess before calling execute_terminate_process.
  3. If a new FlightStep variant was added, extend the match in execute_flight_step instead of reusing execute_terminate_process.

Example fix

// before
execute_terminate_process(&step, ...); // step may be any variant
// after
if let FlightStep::TerminateProcess { .. } = &step {
    execute_terminate_process(&step, ...);
}
Defensive patterns

Strategy: type-guard

Type guard

fn as_terminate(step: &FlightStep) -> Option<&FlightStep> {
    match step {
        FlightStep::TerminateProcess { .. } => Some(step),
        _ => None,
    }
}

Prevention

When it happens

Trigger: A code path (or test) calls execute_terminate_process with a Move/Copy/Symlink/Run/Remove step instead of routing it through execute_flight_step's match. Not reachable through normal cask execution.

Common situations: Development-time mistake when adding a new FlightStep variant or refactoring step dispatch; tests constructing steps manually and passing the wrong variant to execute_terminate_process.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/aba5a30e4a04a0d7. Report an issue: GitHub.