{"record":{"id":"5ae0493f2306bf1c","repo":"jdx/mise","slug":"brew-cask-generic-artifact-source-has-no-filename","errorCode":null,"errorMessage":"brew-cask: generic artifact source has no filename","messagePattern":"brew-cask: generic artifact source has no filename","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/mod.rs","lineNumber":2576,"sourceCode":"            .ok_or_else(|| eyre!(\"brew-cask: generic artifact target has no filename\"))?;\n        nix::fcntl::renameat(&parent.fd, from_name, &parent.fd, to_name)?;\n        Ok(())\n    }\n    #[cfg(not(unix))]\n    {\n        let _ = expected_parent;\n        file::rename(from, to)\n    }\n}\n\nfn ditto(from: &Path, to: &Path) -> Result<()> {\n    let status = std::process::Command::new(\"ditto\")\n        .arg(from)\n        .arg(to)\n        .status()\n        .wrap_err(\"failed to run ditto\")?;\n    if !status.success() {\n        bail!(\n            \"ditto failed copying {} to {}\",\n            from.display(),\n            to.display()\n        );\n    }\n    Ok(())\n}\n\n/// Run a helper with its working directory bound to `dir` via `fchdir`, so\n/// relative arguments resolve from that exact directory inode.\n///\n/// Passing a pathname to a subprocess would let it re-resolve every component,\n/// which a same-uid replacement can redirect. `fchdir` in the child pins\n/// resolution to the descriptor mise already verified, so relative names cannot\n/// escape the validated application directory.\n#[cfg(unix)]\nfn run_in_trusted_dir<Fd: std::os::fd::AsFd>(\n    program: &str,","sourceCodeStart":2558,"sourceCodeEnd":2594,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/packages/brew/cask/mod.rs#L2558-L2594","documentation":"During a trusted generic-artifact rename/backup, mise extracts the file-name component of the source path; if the path has no file name (it is a filesystem root or ends with no name component), the operation cannot proceed and mise returns this eyre error. A path without a filename cannot be renamed within its parent, so the backend fails fast.","triggerScenarios":"rename_trusted_generic_target receives a source path like '/' or a path whose file_name() is None (trailing-root path); an artifact record containing a root or empty path; corrupted target records from a previous install.","commonSituations":"Corrupted or hand-edited artifact target records containing '/' or empty strings; prefix set to '/' so artifact paths resolve to root; migration bugs producing malformed recorded paths.","solutions":["Fix the artifact record so it contains a concrete file path with a name component, not a root path.","Check your prefix configuration — a prefix of '/' will make artifact paths resolve to root; use a real prefix directory.","Reinstall the cask to regenerate valid target records.","Inspect and prune stale/corrupted target records left by an earlier mise or prefix layout."],"exampleFix":"// before (corrupted record)\nrecord.path = \"/\"\n// after (valid record)\nrecord.path = \"/opt/homebrew/share/mytool/data.bin\"","handlingStrategy":"validation","validationCode":"if src.file_name().is_none() {\n    eprintln!(\"source path must include a file name, got: {}\", src.display());\n    std::process::exit(1);\n}","typeGuard":"fn has_filename(p: &std::path::Path) -> bool {\n    p.file_name().is_some()\n}","tryCatchPattern":null,"preventionTips":["Never set a prefix to '/' when installing casks with generic artifacts.","Keep artifact records pointing at concrete named files.","Reinstall casks to regenerate corrupted records.","Validate recorded paths end with a name component before processing."],"tags":["brew-cask","rename","invalid-path"],"backgroundTag":"invalid-argument-value","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}