jdx/mise · error

brew-cask: requested token '{requested_token}' does not matc

Error message

brew-cask: requested token '{requested_token}' does not match API token '{}'

What it means

validate_cask_identity (src/system/packages/brew/cask.rs:951) compares the token the user requested with the `token` field of the fetched cask JSON. They must match, unless the request hit the official homebrew/cask API and the requested name appears in the cask's aliases or old_tokens. For third-party taps no alias is trusted, so any mismatch aborts before anything is staged or downloaded further.

Source

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

                 Tapped casks must publish API metadata at api/cask/<token>.json"
            )
        })?;
    cask.raw_base = raw_base;
    validate_cask_identity(&cask, requested_token, official_api)?;
    Ok(cask)
}

fn validate_cask_identity(cask: &Cask, requested_token: &str, official_api: bool) -> Result<()> {
    validate_cask_path_component("API token", &cask.token)?;
    validate_cask_path_component("version", &cask.version)?;
    let trusted_alias = official_api
        && cask
            .aliases
            .iter()
            .chain(&cask.old_tokens)
            .any(|alias| alias == requested_token);
    if cask.token != requested_token && !trusted_alias {
        bail!(
            "brew-cask: requested token '{requested_token}' does not match API token '{}'",
            cask.token
        );
    }
    Ok(())
}

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')
        && matches!(components.next(), Some(Component::Normal(_)))
        && components.next().is_none()
        && value != ".metadata"
        && !value.starts_with(".mise-");
    if !valid {
        bail!("brew-cask: invalid {kind} '{value}'");
    }

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Install using the canonical token reported in the error message — it is the cask's declared API token
  2. For renamed official casks, update configs to the new token; aliases/old_tokens keep old names working only on the official API
  3. If you maintain the tap, make the cask file's declared token match the token users request (or add the requested name as an alias if the tap also serves the official API path — aliases are still untrusted there, so renaming is the real fix)

Example fix

# before (mise.toml)
name = "firefox-esr-old"

# after — use the API token shown in the error
name = "firefox-esr"
Defensive patterns

Strategy: validation

Validate before calling

let cask: Cask = fetch_cask_json(name).await?;
if cask.token != requested
    && !(official_api && cask.aliases.iter().chain(&cask.old_tokens).any(|a| a == requested))
{
    return Err(anyhow!("use canonical token {} instead of {}", cask.token, requested));
}

Type guard

fn tokens_match(cask: &Cask, requested: &str, official: bool) -> bool {
    cask.token == requested
        || (official && cask.aliases.iter().chain(&cask.old_tokens).any(|a| a == requested))
}

Prevention

When it happens

Trigger: Requesting a token that differs from the declared token in the tap's api/cask/<token>.json: renamed casks (old token requested, new token in metadata), case differences (Firefox vs firefox), a tapped cask file whose declared token differs from its filename, or a homebrew-core alias used against a third-party tap.

Common situations: Upstream cask renames between versions while user configs still carry the old name; display names typed instead of tokens ('Google Chrome' vs google-chrome); taps that vendored official cask JSON under a local token.

Related errors


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