jdx/mise · error

brew-cask:{}: {kind} terminate_process failure_message must

Error message

brew-cask:{}: {kind} terminate_process failure_message must be a string

What it means

Thrown while parsing a terminate_process step. The optional 'failure_message' may be absent or null (becomes None) or a string shown when termination fails; any other JSON type (number, bool, array, object) is rejected so the failure path always has displayable text.

Source

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

                    .iter()
                    .map(|value| {
                        value.as_str().map(str::to_string).ok_or_else(|| {
                            eyre!(
                                "brew-cask:{}: {kind} terminate_process notices must be strings",
                                cask.token
                            )
                        })
                    })
                    .collect::<Result<Vec<_>>>()?,
                Some(_) => bail!(
                    "brew-cask:{}: {kind} terminate_process notices must be an array",
                    cask.token
                ),
            };
            let failure_message = match object.get("failure_message") {
                None | Some(Value::Null) => None,
                Some(Value::String(value)) => Some(value.clone()),
                Some(_) => bail!(
                    "brew-cask:{}: {kind} terminate_process failure_message must be a string",
                    cask.token
                ),
            };
            Ok(FlightStep::TerminateProcess {
                name: name.to_string(),
                match_mode,
                sudo,
                attempts,
                must_succeed,
                notices,
                failure_message,
            })
        }
        _ => bail!(
            "brew-cask:{}: unsupported {kind} step type {}",
            cask.token,
            step_type

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Make failure_message a plain string: "failure_message": "Could not stop x; continue manually"
  2. Or remove the key / set it to null when no custom failure text is needed

Example fix

// before
{"type": "terminate_process", "name": "x", "failure_message": {"text": "failed"}}
// after
{"type": "terminate_process", "name": "x", "failure_message": "failed"}
Defensive patterns

Strategy: validation

Validate before calling

fn failure_message_ok(step: &serde_json::Value) -> bool {
    match step.get("failure_message") {
        None | Some(serde_json::Value::Null) => true,
        Some(serde_json::Value::String(_)) => true,
        Some(_) => false,
    }
}

Try / catch

match parse_flight_step(&cask, kind, &step) {
    Ok(step) => { /* proceed */ }
    Err(e) if e.to_string().contains("failure_message must be a string") => {
        eprintln!("failure_message must be a plain string or null");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: {"type": "terminate_process", "name": "x", "failure_message": 42} or "failure_message": ["msg"] inside preflight_steps/postflight_steps.

Common situations: Numeric exit-code-like values or nested objects put where a message string belongs; generators emitting structured messages ({"text": ...}) instead of plain strings.

Related errors


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