jdx/mise · error

brew-cask: invalid {kind} '{value}'

Error message

brew-cask: invalid {kind} '{value}'

What it means

mise validates cask path components (API token and version) before using them in filesystem/cache paths. The value must be a single, non-empty, normal path component: no empty string, NUL, backslash, leading '.', traversal ('..' / root / prefix), and must not be the reserved name '.metadata' or start with '.mise-'. When the token or version reported by the cask metadata violates any of these rules, the fetch is aborted with this error to prevent path injection and cache collisions.

Source

Thrown at src/system/packages/brew/cask/fetch.rs:144

        bail!(
            "brew-cask: requested token '{requested_token}' does not match API token '{}'",
            cask.token
        );
    }
    Ok(())
}

pub(super) fn validate_cask_path_component(kind: &str, value: &str) -> Result<()> {
    let mut components = Path::new(value).components();
    let valid = !value.is_empty()
        && !value.contains('\0')
        && !value.contains('\\')
        && matches!(components.next(), Some(Component::Normal(_)))
        && components.next().is_none()
        && value != ".metadata"
        && !value.starts_with(".mise-");
    if !valid {
        bail!("brew-cask: invalid {kind} '{value}'");
    }
    Ok(())
}

pub(super) async fn fetch_and_stage(cask: &Cask, pr: Option<&dyn SingleReport>) -> Result<PathBuf> {
    if cask.url.ends_with(".git") {
        return fetch_git_clone_and_stage(cask, pr).await;
    }
    let archive = fetch_archive(cask, pr).await?;
    extract_archive(cask, &archive, pr)
}

pub(super) async fn fetch_git_clone_and_stage(
    cask: &Cask,
    pr: Option<&dyn SingleReport>,
) -> Result<PathBuf> {
    let extract_dir = crate::dirs::CACHE
        .join("system-brew")

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Check the cask metadata source (official API JSON or tap file) and fix the token/version fields to a single normal path component.
  2. Clear the cached cask metadata (mise cache for system-brew) and retry so stale bad metadata is refetched.
  3. If the cask is from a third-party tap that mise cannot validate, install it with the brew CLI directly instead of mise.
  4. Report/patch the offending cask upstream so its version/token becomes a valid component.

Example fix

// offending cask metadata
{"token": "my app", "version": ".metadata"}
// after (valid single component)
{"token": "my-app", "version": "1.2.3"}
Defensive patterns

Strategy: validation

Validate before calling

fn valid_cask_component(v: &str) -> bool {
    use std::path::{Component, Path};
    let mut c = Path::new(v).components();
    !v.is_empty() && !v.contains('\0') && !v.contains('\\')
        && matches!(c.next(), Some(Component::Normal(_)))
        && c.next().is_none()
        && v != ".metadata" && !v.starts_with(".mise-")
}

Type guard

fn is_normal_single_component(v: &str) -> bool {
    matches!(Path::new(v).components().collect::<Vec<_>>()[..], [Component::Normal(_)])
}

Prevention

When it happens

Trigger: Calling a brew-cask-backed install (fetch_cask) or validate_cask_identity with cask metadata whose token or version is empty, contains '/', '\\', '\0', starts with '.', equals '.metadata', or starts with '.mise-'; e.g. a tap serving a cask JSON with a version like '../x', '.metadata', or an empty token.

Common situations: Third-party or homemade taps with malformed cask JSON; an upstream cask whose version field changed to a non-standard value; a misconfigured alias/old_tokens entry feeding a bad token; a corrupted or hand-edited cask metadata cache.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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