jdx/mise · error

brew-cask: command_wrapper requires content or executable, n

Error message

brew-cask: command_wrapper requires content or executable, not both

What it means

The content/executable pair is mutually exclusive: 'content' is a literal script body while 'executable' generates an exec wrapper, so setting both leaves the intended behavior undefined and mise bails with 'not both'. This is the (true, true) arm of the same match that enforces the required-field case.

Source

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

        bail!(
            "brew-cask: command_wrapper has unsupported option {}",
            unsupported.join(", ")
        );
    }
    let content = options
        .get("content")
        .and_then(Value::as_str)
        .map(str::to_string);
    let executable = options
        .get("executable")
        .and_then(Value::as_str)
        .map(str::to_string);
    match (content.is_some(), executable.is_some()) {
        (false, false) => {
            bail!("brew-cask: command_wrapper requires content or executable")
        }
        (true, true) => {
            bail!("brew-cask: command_wrapper requires content or executable, not both")
        }
        _ => {}
    }
    let args = options
        .get("args")
        .map(|args| {
            args.as_array()
                .ok_or_else(|| eyre!("brew-cask: command_wrapper args must be an array"))?
                .iter()
                .map(|arg| {
                    arg.as_str()
                        .map(str::to_string)
                        .ok_or_else(|| eyre!("brew-cask: command_wrapper args must be strings"))
                })
                .collect::<Result<Vec<_>>>()
        })
        .transpose()?
        .unwrap_or_default();

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Keep 'executable' if you just want to wrap a payload binary with args/env; delete the 'content' key.
  2. Keep 'content' if you need a fully custom script; delete the 'executable' key.
  3. In editors/linters for cask metadata, enforce the xor of the two keys.

Example fix

# before
command_wrapper: [["tool", {"content": "#!/bin/sh\nexec tool \"$@\"", "executable": "bin/tool"}]]

# after
command_wrapper: [["tool", {"executable": "bin/tool"}]]
Defensive patterns

Strategy: validation

Validate before calling

jq -e '.command_wrapper[]? | .[1] | (has("content") and has("executable")) | not' cask.json >/dev/null || echo 'wrapper sets both content and executable'

Prevention

When it happens

Trigger: Wrapper options containing both keys, e.g. ["tool", {"content": "#!/bin/sh ...", "executable": "bin/tool"}] — caught at src/system/packages/brew/cask.rs:5158 right after both fields are parsed.

Common situations: Copy-paste of an example wrapper followed by adding the other field; metadata merges that union both variants; editing a wrapper from executable to content without deleting the old key.

Related errors


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