{"record":{"id":"c7e53d678a0d5c2c","repo":"jdx/mise","slug":"brew-cask-kind-name-is-ambiguous","errorCode":null,"errorMessage":"brew-cask: {kind} '{name}' is ambiguous: {}","messagePattern":"brew-cask: (.+?) '(.+?)' is ambiguous: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/mod.rs","lineNumber":2820,"sourceCode":"            continue;\n        }\n        let path = target.join(&suffix);\n        if path.is_file() {\n            matches.push(path);\n        }\n    }\n    matches.sort();\n    matches.dedup();\n    single_match(&matches, \"APPDIR artifact\", source)\n}\n\n/// `kind` and `name` build the ambiguity error, e.g. \"brew-cask: APPDIR\n/// artifact 'x' is ambiguous: a, b\".\nfn single_match(matches: &[PathBuf], kind: &str, name: &str) -> Result<Option<PathBuf>> {\n    match matches {\n        [] => Ok(None),\n        [path] => Ok(Some(path.clone())),\n        _ => bail!(\n            \"brew-cask: {kind} '{name}' is ambiguous: {}\",\n            matches\n                .iter()\n                .map(|path| path.display().to_string())\n                .collect::<Vec<_>>()\n                .join(\", \")\n        ),\n    }\n}\n\nfn find_generated_completion_file(root: &Path, executable: &str) -> Result<Option<PathBuf>> {\n    let executable_path = Path::new(executable);\n    let direct = root.join(executable_path);\n    if direct.is_file() {\n        return Ok(Some(direct));\n    }\n    let matches = find_file_artifacts(root, executable_path);\n    single_match(&matches, \"completion executable\", executable)","sourceCodeStart":2802,"sourceCodeEnd":2838,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/cask/mod.rs#L2802-L2838","documentation":"Cask artifact globs can match multiple staged files. `single_match` is mise's disambiguation helper: it accepts exactly zero or one match and throws this error when more than one path matches, listing all candidates. The cask definition is then too vague for mise to know which artifact to link.","triggerScenarios":"A helper resolving an artifact by glob (e.g. APPDIR artifacts, as the doc comment shows) receives a `matches` slice with 2+ PathBufs and calls `bail!` with the joined candidate list.","commonSituations":"A cask glob like `*.app` or `bin/*` matches several staged entries after an upstream release added new files; a too-broad wildcard in a custom cask; upstream restructured its payload so a previously unique match is now duplicated.","solutions":["Inspect the candidate list in the message and tighten the cask's artifact glob to match exactly one path","Pin the artifact name to the specific file you want instead of a wildcard","Update the cask definition after upstream restructures its payload","Report the cask to its maintainer if the upstream change made the pattern ambiguous"],"exampleFix":"// before (cask stanza)\napp \"*/*.app\"\n// after\napp \"MyTool.app\"","handlingStrategy":"validation","validationCode":"# preview the glob before installing\ncount=$(find <stage-dir> -path '<glob>' | wc -l); [ \"$count\" -le 1 ] || echo \"ambiguous: $count matches\"","typeGuard":null,"tryCatchPattern":"match result {\n  Err(e) if e.contains(\"is ambiguous\") => {\n    let candidates = e.split(\": \").last();\n    eprintln!(\"tighten the cask artifact glob to one of: {candidates:?}\");\n  }\n  Err(e) => return Err(e),\n  Ok(v) => v,\n}","preventionTips":["Prefer exact artifact names over wildcards in cask definitions","Re-check globs after upstream restructures its payload","Dry-run/list the staged files when authoring a cask"],"tags":["brew-cask","glob","ambiguity","cask-definition"],"backgroundTag":"ambiguous-artifact-match","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}