{"record":{"id":"84eee37a0c3303fa","repo":"jdx/mise","slug":"invalid-completion-cache-identity","errorCode":null,"errorMessage":"invalid completion cache identity","messagePattern":"invalid completion cache identity","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/packslip.rs","lineNumber":1134,"sourceCode":"/// The `shell` completion script for `tool`, from the packslip of the\n/// version that is active right now.\nfn completion_bin<'a>(statement: &'a Statement, tool: Option<&'a str>) -> Option<&'a str> {\n    tool.map(packslip::command_name)\n        .filter(|name| {\n            statement\n                .predicate\n                .artifacts\n                .iter()\n                .flat_map(|a| &a.bin)\n                .any(|b| b.name == *name)\n        })\n        .or_else(|| statement.sole_bin())\n}\n\nfn completion_cache_path(install_path: &Path, tool: &str, shell: &str) -> Result<PathBuf> {\n    let bin = packslip::command_name(tool);\n    if !file::is_plain_file_name(bin) || !file::is_plain_file_name(shell) {\n        bail!(\"invalid completion cache identity\");\n    }\n    Ok(install_path\n        .join(RESOURCES_DIR)\n        .join(\"completions-v2\")\n        .join(bin)\n        .join(format!(\"{shell}.completion\")))\n}\n\npub(crate) async fn completion_script(\n    config: &Arc<Config>,\n    tool: &str,\n    shell: &str,\n) -> Result<String> {\n    let ts = config.get_toolset().await?;\n    let (backend, tv) = find_tool(config, ts, tool).await?;\n    let install_path = tv.install_path();\n    let Some(statement) = statement(&install_path)? else {\n        bail!(","sourceCodeStart":1116,"sourceCodeEnd":1152,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/packslip.rs#L1116-L1152","documentation":"completion_cache_path builds the on-disk path where a generated completion script is cached (resources/completions-v2/<bin>/<shell>.completion). Before building it, it validates that both the binary name and the shell name are plain file names (no path separators, '..', etc.). If either contains path-like or unsafe characters, mise refuses to construct the cache path to prevent path traversal or corrupt cache layout.","triggerScenarios":"Calling completion_script (via `mise completion <shell> --tool <tool>`) where packslip::command_name(tool) or the shell argument resolves to a value that is not a plain file name — e.g. a tool name containing '/' or a shell string with directory components.","commonSituations":"A tool name containing slashes or unusual characters; passing a malformed shell identifier; a packslip naming a binary with a path-like name.","solutions":["Use a plain tool/command name (no '/', '..', or separators) in `mise completion <shell> --tool <name>`.","Pass a supported shell name exactly: bash, zsh, fish, or pwsh.","If a packslip declares a bin name that is not a plain file name, fix the statement to name just the executable."],"exampleFix":"// before\nmise completion bash --tool gh/cli\n// after\nmise completion bash --tool gh","handlingStrategy":"validation","validationCode":"fn plain_name(s: &str) -> bool { !s.is_empty() && !s.contains(['/', '\\\\']) && s != \".\" && s != \"..\" }\nassert!(plain_name(tool) && plain_name(shell));","typeGuard":"fn is_plain_file_name(s: &str) -> bool { !s.is_empty() && !s.contains('/') && !s.contains('\\\\') && s != \".\" && s != \"..\" }","tryCatchPattern":"if !is_plain_file_name(tool) || !is_plain_file_name(shell) { return Err(\"invalid completion cache identity\".into()); }\nlet script = completion_script(&config, tool, shell)?;","preventionTips":["Always pass bare tool/command names, never paths, to `mise completion --tool`.","Use one of the canonical shell names: bash, zsh, fish, pwsh.","Validate bin names in packslip statements before publishing."],"tags":["completions","packslip","validation","path-safety"],"backgroundTag":"invalid-argument-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"}