{"record":{"id":"f456e1e5b64d7106","repo":"jdx/mise","slug":"brew-cask-invalid-completion-target-target-name","errorCode":null,"errorMessage":"brew-cask: invalid completion target '{target_name}'","messagePattern":"brew-cask: invalid completion target '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask.rs","lineNumber":4495,"sourceCode":"            }\n        }\n        CompletionShell::Zsh => {\n            if filename.starts_with('_') {\n                filename.to_string()\n            } else {\n                format!(\"_{stem}\")\n            }\n        }\n        CompletionShell::Pwsh => {\n            if filename.ends_with(\".ps1\") {\n                filename.to_string()\n            } else {\n                format!(\"{stem}.ps1\")\n            }\n        }\n    };\n    if normalized.is_empty() {\n        bail!(\"brew-cask: invalid completion target '{target_name}'\");\n    }\n    Ok(normalized)\n}\n\nfn caskroom_completion_path(caskroom: &Path, target: &Path) -> Result<PathBuf> {\n    let prefix = prefix::prefix();\n    let relative = target.strip_prefix(&prefix).map_err(|_| {\n        eyre!(\n            \"brew-cask: completion target '{}' must be under {}\",\n            target.display(),\n            prefix.display()\n        )\n    })?;\n    if relative.components().next().is_none() {\n        bail!(\n            \"brew-cask: invalid completion target '{}'\",\n            target.display()\n        );","sourceCodeStart":4477,"sourceCodeEnd":4513,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/system/packages/brew/cask.rs#L4477-L4513","documentation":"completion_filename normalizes a completion target for the target shell (stripping or adding prefixes like '_' and suffixes like '.ps1'/'.zsh' per CompletionShell). If that normalization produces an empty string — for example a target that is only dots, only an extension, or otherwise reduces to nothing — mise rejects it with this bail instead of trying to build a path from an empty filename.","triggerScenarios":"A cask completion target such as '.', '..', '' or a value whose stem is empty after shell-specific normalization (e.g. a Pwsh target that normalizes to just '.ps1' with an empty stem, or a zsh target reducing to '_'). The check `if normalized.is_empty()` at src/system/packages/brew/cask.rs:4495 fires after the match on CompletionShell.","commonSituations":"Malformed or machine-generated cask metadata with an empty/placeholder target field; YAML/JSON field misindentation that yields an empty string; adversarial or fuzzed cask JSON probing mise's filename handling.","solutions":["Set the completion target to a real filename with a non-empty stem, e.g. '_tool' for zsh or 'tool.ps1' for Pwsh.","Validate the cask metadata loads as you expect (jq/python) — an empty string usually means the field was never populated or was misnested.","If generating cask metadata programmatically, assert the normalized filename is non-empty before emitting the stanza."],"exampleFix":"# before\n\"completions\": { \"target\": \"\" }\n\n# after\n\"completions\": { \"target\": \"_mytool\" }","handlingStrategy":"validation","validationCode":"# require a non-empty stem in every completion target\njq -e '.completions[] | select((.target | split(\".\") | first | length) > 0)' meta.json >/dev/null || echo 'empty completion target'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Require a non-empty filename stem in cask metadata schemas.","Fail fast in generators when any normalized completion filename is empty.","Round-trip generated metadata through a JSON schema validator before publishing."],"tags":["brew-cask","completions","filename-validation","mise"],"backgroundTag":"invalid-filename","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}