{"record":{"id":"c7cf1c7a53121940","repo":"jdx/mise","slug":"invalid-github-tap-url-url","errorCode":null,"errorMessage":"invalid GitHub tap URL '{url}'","messagePattern":"invalid GitHub tap URL '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/tap.rs","lineNumber":248,"sourceCode":"\nfn github_repository<'a>(\n    owner: &'a str,\n    tap: &'a str,\n    tap_url: Option<&'a str>,\n) -> Result<(&'a str, String)> {\n    let Some(url) = tap_url else {\n        return Ok((owner, format!(\"homebrew-{tap}\")));\n    };\n    let normalized = url.trim_end_matches('/').trim_end_matches(\".git\");\n    let rest = normalized\n        .strip_prefix(\"https://github.com/\")\n        .ok_or_else(|| eyre::eyre!(\"only GitHub tap URLs can be fetched directly\"))?;\n    let mut parts = rest.split('/');\n    match (parts.next(), parts.next(), parts.next()) {\n        (Some(repo_owner), Some(repo), None) if !repo_owner.is_empty() && !repo.is_empty() => {\n            Ok((repo_owner, repo.to_string()))\n        }\n        _ => bail!(\"invalid GitHub tap URL '{url}'\"),\n    }\n}\n\nasync fn fetch_formula_source(tap_source: &TapSource, name: &str) -> Result<(String, String)> {\n    let root_tree: GithubTree = HTTP_FETCH\n        .json_cached(format!(\n            \"{}/git/trees/{}\",\n            tap_source.api_base, tap_source.commit\n        ))\n        .await\n        .wrap_err(\"failed to inspect tap formula directories\")?;\n    if root_tree.truncated {\n        bail!(\"tap repository tree was truncated\");\n    }\n\n    let (directory, formula_tree) =\n        if let Some((directory, sha)) = active_formula_directory(&root_tree) {\n            let tree: GithubTree = HTTP_FETCH","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/tap.rs#L230-L266","documentation":"mise can fetch tap sources directly only from GitHub URLs of the form https://github.com/<owner>/<repo>. `github_repository` parses the URL and requires exactly owner/repo segments; anything else (extra path segments, empty components, non-GitHub hosts reaching this parser) bails with this message.","triggerScenarios":"`resolve_tap_source` -> `github_repository` given a URL like `https://github.com/owner/repo/tree/branch` or `https://gitlab.com/owner/repo`, i.e. more or fewer than exactly two non-empty path segments after the host.","commonSituations":"Typing a full tap URL with a subpath or trailing slash segments; using a GitLab/Codeberg tap URL where direct fetch expects GitHub; copy-pasting a GitHub URL that includes `/tree/<ref>` from a browser.","solutions":["Use the bare repository URL `https://github.com/<owner>/<repo>` with no extra path segments","Reference the tap by short form (`owner/repo`) instead of a full URL","Do not include /tree/<branch> or .git suffixes in the tap URL","For non-GitHub taps, clone/locate the tap through a supported mechanism instead of direct URL fetch"],"exampleFix":"// before\nmise x brew --tap \"https://github.com/owner/repo/tree/main\"\n// after\nmise x brew --tap \"owner/repo\"","handlingStrategy":"validation","validationCode":"let path = url.strip_prefix(\"https://github.com/\").ok_or(\"not github\")?;\nlet segs: Vec<_> = path.split('/').filter(|s| !s.is_empty()).collect();\nif segs.len() != 2 { eprintln!(\"use bare owner/repo GitHub URL\"); }","typeGuard":"fn parse_github_tap(url: &str) -> Option<(String, String)> {\n    let rest = url.strip_prefix(\"https://github.com/\")?;\n    let mut it = rest.split('/');\n    let o = it.next()?; let r = it.next()?; let n = it.next();\n    (n.is_none() && !o.is_empty() && !r.is_empty()).then(|| (o.into(), r.into()))\n}","tryCatchPattern":null,"preventionTips":["Use short-form owner/repo tap references","Strip /tree/<ref> and .git suffixes from GitHub URLs before passing them","Remember only GitHub taps support direct URL fetching"],"tags":["homebrew","tap","url","github"],"backgroundTag":"invalid-url-format","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}