{"record":{"id":"2045b2cb6bd3a54a","repo":"jdx/mise","slug":"brew-cask-command-wrapper-requires-a-command-name-2045b2","errorCode":null,"errorMessage":"brew-cask: command_wrapper requires a command name without path components","messagePattern":"brew-cask: command_wrapper requires a command name without path components","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/artifacts.rs","lineNumber":191,"sourceCode":"\npub(super) fn parse_command_wrapper_artifact(\n    value: &Value,\n) -> Result<Option<CommandWrapperArtifact>> {\n    let Some(wrapper) = value.as_object().and_then(|o| o.get(\"command_wrapper\")) else {\n        return Ok(None);\n    };\n    let values = wrapper\n        .as_array()\n        .ok_or_else(|| eyre!(\"brew-cask: command_wrapper metadata must be an array\"))?;\n    let name = values\n        .first()\n        .and_then(Value::as_str)\n        .ok_or_else(|| eyre!(\"brew-cask: command_wrapper requires a command name\"))?;\n    let name_path = Path::new(name);\n    if name_path.file_name().and_then(|name| name.to_str()) != Some(name)\n        || matches!(name, \".\" | \"..\")\n    {\n        bail!(\"brew-cask: command_wrapper requires a command name without path components\");\n    }\n    let options = values\n        .get(1)\n        .and_then(Value::as_object)\n        .ok_or_else(|| eyre!(\"brew-cask: command_wrapper requires options\"))?;\n    let mut unsupported = options\n        .keys()\n        .filter(|key| !matches!(key.as_str(), \"content\" | \"executable\" | \"args\" | \"env\"))\n        .cloned()\n        .collect::<Vec<_>>();\n    unsupported.sort();\n    if !unsupported.is_empty() {\n        bail!(\n            \"brew-cask: command_wrapper has unsupported option {}\",\n            unsupported.join(\", \")\n        );\n    }\n    let content = options","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/packages/brew/cask/artifacts.rs#L173-L209","documentation":"This error is thrown by parse_command_wrapper_artifact when a Homebrew cask `command_wrapper` artifact declares a command name that contains path components (e.g. 'bin/tool' or './tool'). The library requires a bare executable name so the wrapper can be installed under a single file name in the command directory.","triggerScenarios":"Parsing a cask artifact stanza whose command_wrapper `name` value is a string containing '/' or path separators, is '.' or '..', or whose final path component does not equal the whole string.","commonSituations":"Copy-pasting an executable path from a Homebrew formula or absolute install path into the command_wrapper name field; authoring a cask definition by hand and using 'bin/foo' instead of 'foo'.","solutions":["Use only the bare command/file name without '/' or '.' components, e.g. 'mytool' instead of 'bin/mytool'.","Verify the name is not '.' or '..'.","If the executable lives in a subdirectory, express that elsewhere (e.g. in the executable/content options) and keep name as the final component."],"exampleFix":"// before\n\"command_wrapper\" => json!([\"bin/mytool\", {\"executable\": \"mytool\"}])\n// after\n\"command_wrapper\" => json!([\"mytool\", {\"executable\": \"mytool\"}])","handlingStrategy":"validation","validationCode":"fn valid_cw_name(name: &str) -> bool {\n    let p = std::path::Path::new(name);\n    p.file_name().and_then(|f| f.to_str()) == Some(name) && !matches!(name, \".\" | \"..\")\n}\nassert!(valid_cw_name(\"mytool\"));","typeGuard":"fn valid_cw_name(name: &str) -> bool {\n    std::path::Path::new(name)\n        .file_name()\n        .and_then(|f| f.to_str())\n        == Some(name)\n        && !matches!(name, \".\" | \"..\")\n}","tryCatchPattern":null,"preventionTips":["Always use the bare binary name in command_wrapper name fields","Add a lint/test validating no '/' in command names","Never use '.' or '..' as artifact names"],"tags":["brew-cask","validation","path","config"],"backgroundTag":"invalid-identifier-format","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"}