jdx/mise · error

brew-cask: invalid completion target '{}'

Error message

brew-cask: invalid completion target '{}'

What it means

caskroom_completion_path maps a validated completion target into the cask's private caskroom by stripping the brew prefix from it. If stripping leaves an empty relative path — i.e. the resolved target is exactly the brew prefix itself — there is no file component to relocate and mise bails. It is the degenerate-target guard between the strip_prefix containment check and the final caskroom.join.

Source

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

        }
    };
    if normalized.is_empty() {
        bail!("brew-cask: invalid completion target '{target_name}'");
    }
    Ok(normalized)
}

fn caskroom_completion_path(caskroom: &Path, target: &Path) -> Result<PathBuf> {
    let prefix = prefix::prefix();
    let relative = target.strip_prefix(&prefix).map_err(|_| {
        eyre!(
            "brew-cask: completion target '{}' must be under {}",
            target.display(),
            prefix.display()
        )
    })?;
    if relative.components().next().is_none() {
        bail!(
            "brew-cask: invalid completion target '{}'",
            target.display()
        );
    }
    Ok(caskroom.join(relative))
}

fn completion_target_paths(cask: &Cask, artifacts: &CaskArtifacts) -> Result<Vec<PathBuf>> {
    let mut targets = artifacts
        .completions
        .iter()
        .map(CompletionArtifact::target_path)
        .collect::<Result<Vec<_>>>()?;
    for generated in &artifacts.generated_completions {
        targets.extend(generated.target_paths(cask)?);
    }
    targets.sort();
    targets.dedup();

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Point the completion target at a concrete file under the prefix, e.g. 'share/zsh/site-functions/_tool', not a directory or the prefix itself.
  2. Check how the target value was produced — a leading variable that expanded to empty often yields the bare prefix.
  3. Add an authoring-time lint: target must contain at least one path component below the prefix.

Example fix

# before — target resolves to the prefix itself
"target": "/opt/homebrew"

# after
"target": "/opt/homebrew/share/zsh/site-functions/_tool"
Defensive patterns

Strategy: validation

Validate before calling

# target must have at least one component below the brew prefix
PREFIX="$(brew --prefix)"
case "$TARGET" in "$PREFIX"|"$PREFIX/") echo 'target is the prefix itself'; exit 1;; esac

Prevention

When it happens

Trigger: A completion target that resolves to the brew prefix root: an absolute target equal to the prefix (e.g. '/opt/homebrew'), or one that normalizes to it. `relative.components().next().is_none()` at src/system/packages/brew/cask.rs:4510 is true only when strip_prefix consumed the entire path.

Common situations: Cask metadata where the target field accidentally holds the prefix or '/' after templating; hand-written stanzas that pasted a directory instead of a file path; programmatic cask generation that emits the install root when a variable is empty.

Related errors


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