{"record":{"id":"615be84966f615ee","repo":"jdx/mise","slug":"brew-cask-invalid-binary-target","errorCode":null,"errorMessage":"brew-cask: invalid binary target '{}'","messagePattern":"brew-cask: invalid binary target '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask.rs","lineNumber":4936,"sourceCode":"    let roots = if is_appdir_binary_target(&binary.target_name()?) {\n        let mut roots = allowed_appdir_roots()?;\n        roots.extend(allowed_binary_target_roots());\n        roots\n    } else {\n        allowed_binary_target_roots()\n    };\n    let relative = roots\n        .iter()\n        .find_map(|root| target.strip_prefix(root).ok())\n        .ok_or_else(|| {\n            eyre!(\n                \"brew-cask: binary target '{}' must be under {}\",\n                target.display(),\n                allowed_binary_target_roots_display(&roots)\n            )\n        })?;\n    if relative.components().next().is_none() {\n        bail!(\n            \"brew-cask: invalid binary target '{}'\",\n            binary.target_name()?\n        );\n    }\n    Ok(caskroom.join(relative))\n}\n\nfn cask_artifacts(cask: &Cask) -> Result<CaskArtifacts> {\n    let mut artifacts = CaskArtifacts::default();\n    for artifact in &cask.artifacts {\n        let artifact_type = artifact_type(artifact);\n        if let Some(steps) = parse_flight_steps(cask, artifact, \"preflight_steps\")? {\n            artifacts.preflight_steps.extend(steps);\n            continue;\n        }\n        if let Some(steps) = parse_flight_steps(cask, artifact, \"postflight_steps\")? {\n            artifacts.postflight_steps.extend(steps);\n            continue;","sourceCodeStart":4918,"sourceCodeEnd":4954,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/system/packages/brew/cask.rs#L4918-L4954","documentation":"caskroom_binary_path validates that a binary artifact's target lies under an allowed root (the brew prefix, plus /usr/local when different) and then strips that root to compute the path inside the caskroom. If stripping leaves zero components — the target IS the root itself (e.g. '$APPDIR/', the bare prefix, or '/') — there is no file component to link and mise bails with the binary's target_name.","triggerScenarios":"A binary stanza target that resolves exactly to an allowed root: target '$APPDIR/' with nothing after it, '/' , the literal brew prefix, or any path normalizing to one of allowed_binary_target_roots(). The guard is `relative.components().next().is_none()` at src/system/packages/brew/cask.rs:4936; note this is the sibling check to the 'must be under' error that fires when the target is outside the roots.","commonSituations":"Cask metadata where the binary target field was left as a directory or templated to empty; hand-converted Homebrew stanzas ('target: $APPDIR' pasted whole); schema changes where a list field collapsed to a bare root string.","solutions":["Give the binary target a concrete destination filename, e.g. '$APPDIR/MyApp.app/Contents/MacOS/tool' or 'bin/tool'.","If you intended a simple install into the brew bin, use a bare target name like 'tool' rather than a directory path.","Lint cask metadata before install: every binary target must have at least one component below its root."],"exampleFix":"# before\n\"binary\": [[\"MyApp.app/Contents/MacOS/tool\", \"$APPDIR/\"]]\n\n# after\n\"binary\": [[\"MyApp.app/Contents/MacOS/tool\", \"tool\"]]","handlingStrategy":"validation","validationCode":"# every binary target needs a component below its root\njq -r '.binaries[] | .target // empty' meta.json | while read -r t; do\n  case \"$t\" in \"$APPDIR\"|\"$APPDIR/\"|\"/\"|\"$(brew --prefix)\") echo \"degenerate target: $t\";; esac\ndone","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Author binary targets as concrete filenames ('tool') or full destinations, never bare roots.","Assert every target has a non-empty remainder after stripping its root.","Validate templated targets after rendering, when empty variables are visible."],"tags":["brew-cask","binary-artifact","path-validation","mise"],"backgroundTag":"invalid-target-path","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}