{"record":{"id":"b23449dfa031b50d","repo":"jdx/mise","slug":"ditto-failed-copying-to-b23449","errorCode":null,"errorMessage":"ditto failed copying {} to {}","messagePattern":"ditto failed copying (.+?) to (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/mod.rs","lineNumber":2658,"sourceCode":"    let destination = open_dir_nofollow_at(&dir, name).wrap_err_with(|| {\n        format!(\n            \"brew-cask: cannot open staging directory {}\",\n            Path::new(name).display()\n        )\n    })?;\n    let stat = nix::sys::stat::fstat(&destination)?;\n    if stat.st_uid != nix::unistd::geteuid().as_raw() {\n        bail!(\"brew-cask: staging directory is not owned by the current user\");\n    }\n    // `ditto src dst` copies the *contents* of src into dst, so pointing it at\n    // the bound directory reproduces the bundle in place.\n    let status = run_in_trusted_dir(\n        \"ditto\",\n        &[from.as_os_str(), std::ffi::OsStr::new(\".\")],\n        &destination,\n    )?;\n    if !status.success() {\n        bail!(\n            \"ditto failed copying {} to {}\",\n            from.display(),\n            Path::new(name).display()\n        );\n    }\n    // Restore the bundle's own permissions, which the private staging mode hid.\n    if let Ok(metadata) = from.symlink_metadata() {\n        use std::os::unix::fs::PermissionsExt;\n        let mode = nix::sys::stat::Mode::from_bits_truncate(\n            metadata.permissions().mode() as nix::libc::mode_t\n        );\n        nix::sys::stat::fchmod(&destination, mode)?;\n    }\n    Ok(())\n}\n\nfn install_pkg(stage: &Path, pkg: &PkgArtifact) -> Result<()> {\n    let source = find_file_artifact(stage, &pkg.source)","sourceCodeStart":2640,"sourceCodeEnd":2676,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/packages/brew/cask/mod.rs#L2640-L2676","documentation":"mise copies cask bundle contents into its private staging directory by invoking the macOS 'ditto' tool in a trusted directory context. When ditto exits with a non-zero status, mise wraps the failure in this error reporting the source path and the staging destination. Causes include disk-full, permission problems on the source bundle, or source files disappearing mid-copy.","triggerScenarios":"run_in_trusted_dir(\"ditto\", [from, \".\"], destination) returns a failing exit status; the source bundle was deleted or renamed during install; target volume is full or read-only; source contains unreadable/locked files.","commonSituations":"Full APFS volume during large cask installs; downloads folder cleanup racing the install; iCloud-offloaded files that cannot be materialized; quarantine/xattr issues making source files unreadable; running out of disk in ~/Library/Caches.","solutions":["Re-run the cask install; a transient source/IO failure often resolves on retry after the artifact is re-downloaded.","Free disk space on the destination volume and check it is not read-only.","Verify the source bundle path exists and is fully downloaded (clear the cache and re-download the cask).","Check permissions/xattrs on the source files (dequarantine with xattr -dr com.apple.quarantine <path> if needed).","Ensure 'ditto' is present and functional (it ships with macOS; a stripped-down environment may lack it)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"let src = std::path::Path::new(&from);\nif !src.exists() {\n    eprintln!(\"source bundle missing before copy: {}\", src.display());\n    std::process::exit(1);\n}\nlet free = fs_free_bytes(&dest_volume);\nif free < estimated_size {\n    eprintln!(\"insufficient disk space: {free} bytes free\");\n    std::process::exit(1);\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"ditto failed copying\") => {\n        // clear cache, free disk space, then retry install once\n        clear_brew_cache()?;\n        retry_install()?;\n    }\n    r => r?,\n}","preventionTips":["Keep ample free disk space on the destination volume.","Do not touch or clean source downloads while a cask is installing.","Materialize iCloud-offloaded files before installing casks from those paths.","Clear the brew cask cache after any interrupted install and retry.","Ensure the standard macOS 'ditto' tool is available."],"tags":["brew-cask","macos","ditto","copy-failed","disk"],"backgroundTag":"file-write-failed","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"}