{"record":{"id":"79605d521358c27c","repo":"uutils/coreutils","slug":"mv-error-permission-denied","errorCode":null,"errorMessage":"mv-error-permission-denied","messagePattern":"mv-error-permission-denied","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"src/uu/mv/src/mv.rs","lineNumber":1475,"sourceCode":"            {\n                // Create a hardlink to the first moved file instead of copying\n                fs::hard_link(&existing_target, to)?;\n                fs::remove_file(from)?;\n                return Ok(());\n            }\n        }\n    }\n\n    // Open src/dst with O_NOFOLLOW and keep the fds alive across copy,\n    // chown, xattr, and chmod so a concurrent path-swap can't redirect any\n    // step to a different inode.\n    #[cfg(unix)]\n    {\n        use std::fs::Permissions;\n        use std::os::unix::fs::{MetadataExt, PermissionsExt};\n        use uucore::safe_copy::{create_dest_restrictive, open_source};\n        let src_file = open_source(from, /* nofollow */ true)\n            .map_err(|err| io::Error::new(err.kind(), translate!(\"mv-error-permission-denied\")))?;\n        let src_mode = src_file\n            .metadata()\n            .map_err(|err| io::Error::new(err.kind(), translate!(\"mv-error-permission-denied\")))?\n            .mode()\n            & 0o7777;\n        let mut dst_file = create_dest_restrictive(to, /* nofollow */ true)\n            .map_err(|err| io::Error::new(err.kind(), translate!(\"mv-error-permission-denied\")))?;\n        uucore::buf_copy::copy_fast(&mut &src_file, &mut dst_file)\n            .map_err(|err| io::Error::new(err.kind(), translate!(\"mv-error-permission-denied\")))?;\n\n        #[cfg(not(any(target_vendor = \"apple\", target_os = \"redox\")))]\n        {\n            let _ = fsxattr::copy_xattrs_fd_ignore_unsupported(&src_file, &dst_file);\n        }\n\n        // chown before chmod: chown(2) clears setuid/setgid for non-root,\n        // so the final mode must be applied last to preserve those bits.\n        //","sourceCodeStart":1457,"sourceCodeEnd":1493,"githubUrl":"https://github.com/uutils/coreutils/blob/85295bbf788bfd7a6926ba692031563504b304b7/src/uu/mv/src/mv.rs#L1457-L1493","documentation":"rename_file_fallback's Unix path opens the source with open_source(..., nofollow=true) from uucore::safe_copy so the read cannot be swapped to another file mid-move. Any failure opening the source is replaced by this localized permission-denied error (the original err.kind() is kept but the message is generic). It means mv could not obtain a safe handle to the file it is about to copy across devices.","triggerScenarios":"`mv` falls back to copy (cross-device rename) and open_source on the source fails: missing read permission on the file, missing search (x) permission on a parent directory, or the file vanished between stat and open (ENOENT).","commonSituations":"Moving files owned by another user with mode 0600; traversing a directory without execute permission; moving from a directory being concurrently cleaned; AIDE/cleanup daemons deleting files mid-move.","solutions":["Fix source access: chmod/chown the file or get read permission on every parent directory (needs +x on dirs).","Re-run as a user with rights, e.g. `sudo mv`, if policy allows.","Re-check the source still exists (`ls -l`) — it may have been deleted concurrently.","If the source is unreadable but you only need it relocated on the same device, avoid the copy fallback (rename within one filesystem needs no read access)."],"exampleFix":"// before\nmv /secure/id_rsa /mnt/usb/   // mode 0600, other user\n// after\nsudo mv /secure/id_rsa /mnt/usb/ && sudo chown $(id -u) /mnt/usb/id_rsa","handlingStrategy":"validation","validationCode":"fn can_read_source(p: &Path) -> bool {\n    std::fs::File::open(p).is_ok() // or check mode bits on unix\n}\nif !can_read_source(from) { eprintln!(\"no read access to {}\", from.display()); }","typeGuard":"fn readable(p: &Path) -> bool {\n    use std::os::unix::fs::PermissionsExt;\n    std::fs::metadata(p).map(|m| m.mode() & 0o444 != 0).unwrap_or(false)\n}","tryCatchPattern":"match mv_result {\n    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {\n        // advise chmod/chown or sudo; same-device rename still possible\n    }\n    r => r?,\n}","preventionTips":["Verify read permission on the file and +x on all parent dirs before moving","Move within one filesystem when the source is unreadable (rename needs no read)","Use sudo or group ownership for protected files"],"tags":["mv","permissions","filesystem","unix"],"backgroundTag":"permission-denied","analyzedSha":"85295bbf788bfd7a6926ba692031563504b304b7","analyzedAt":"2026-08-31T11:11:36.175Z","contentChangedAt":"2026-08-31T11:11:36.175Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}