jdx/mise · error

brew: tapped formula '{name}' needs a GitHub tap URL in [boo

Error message

brew: tapped formula '{name}' needs a GitHub tap URL in [bootstrap.brew.taps] so mise can fetch metadata directly without the brew CLI

What it means

mise fetches Homebrew formula metadata directly from GitHub (raw.githubusercontent.com) instead of shelling out to the brew CLI. For a formula in a third-party tap (owner/tap/name) it needs the tap's GitHub repository; when a tap URL is configured in [bootstrap.brew.taps] but is not a plain https://github.com/<owner>/<repo> URL (non-GitHub host, SSH URL, or extra path segments), no raw base can be derived and mise refuses rather than silently guessing.

Source

Thrown at src/system/packages/brew/api.rs:163

        .wrap_err_with(|| format!("failed to fetch Homebrew formula '{name}'"))
}

pub async fn formula_with_tap_name(
    name: &str,
    tap_name: Option<&str>,
    tap_url: Option<&str>,
) -> Result<Formula> {
    let Some((owner, tap, formula_name)) = split_tap_name(name).or_else(|| {
        let (owner, tap) = split_tap(tap_name?)?;
        Some((owner, tap, name))
    }) else {
        return formula(name).await;
    };
    if owner == "homebrew" && tap == "core" {
        return formula(formula_name).await;
    }
    let Some(url) = tap_formula_api_url(owner, tap, formula_name, tap_url) else {
        bail!(
            "brew: tapped formula '{name}' needs a GitHub tap URL in [bootstrap.brew.taps] \
             so mise can fetch metadata directly without the brew CLI"
        );
    };
    HTTP_FETCH
        .json_cached::<Formula, _>(url)
        .await
        .wrap_err_with(|| {
            format!(
                "failed to fetch Homebrew tap formula '{name}' directly. \
                 The tap must publish API metadata at api/formula/{formula_name}.json; \
                 mise will not proxy to the brew CLI"
            )
        })
}

pub(super) fn tap_name(name: &str) -> Option<String> {
    let (owner, tap, _) = split_tap_name(name)?;

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Set the tap entry to the bare repository URL: https://github.com/<owner>/<repo> (.git suffix and trailing slash are tolerated)
  2. If the tap follows the homebrew-<name> convention, delete the URL override entirely — mise infers https://github.com/<owner>/homebrew-<tap> automatically
  3. If the tap is not on GitHub, mise cannot fetch its metadata: install that formula with the brew CLI outside mise

Example fix

# before
[bootstrap.brew.taps]
"company/tap" = "https://gitlab.internal/dev/homebrew-tap"

# after
[bootstrap.brew.taps]
"company/tap" = "https://github.com/company/homebrew-tap"
Defensive patterns

Strategy: validation

Validate before calling

fn is_bare_github_url(url: &str) -> bool {
    let u = url.trim_end_matches(".git").trim_end_matches('/');
    u.strip_prefix("https://github.com/").is_some_and(|rest| {
        let mut parts = rest.split('/');
        parts.next().is_some_and(|o| !o.is_empty())
            && parts.next().is_some_and(|r| !r.is_empty())
            && parts.next().is_none()
    })
}

// before resolving brew:user/tap/tool:
assert!(tap_url.map_or(true, is_bare_github_url), "tap URL must be https://github.com/<owner>/<repo>");

Try / catch

Catch the bail and point users at the exact config key: [bootstrap.brew.taps].<tap> must be a bare GitHub https URL; do not attempt any non-GitHub fallback (mise has none by design).

Prevention

When it happens

Trigger: Installing a tapped formula like `mise use brew:user/tap/tool` while [bootstrap.brew.taps] maps that tap to a GitLab/Bitbucket/self-hosted URL, an `git@github.com:...` SSH URL, or a deep link such as https://github.com/owner/repo/tree/main.

Common situations: Companies mirroring taps on internal GitLab; users copying clone URLs with extra segments; assuming mise supports non-GitHub taps for CLI-free metadata fetching (it does not).

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/549879e237f87907. Report an issue: GitHub.