uutils/coreutils · error · io::Error
mv-error-permission-denied
Error message
mv-error-permission-denied
What it means
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.
Source
Thrown at src/uu/mv/src/mv.rs:1475
{
// Create a hardlink to the first moved file instead of copying
fs::hard_link(&existing_target, to)?;
fs::remove_file(from)?;
return Ok(());
}
}
}
// Open src/dst with O_NOFOLLOW and keep the fds alive across copy,
// chown, xattr, and chmod so a concurrent path-swap can't redirect any
// step to a different inode.
#[cfg(unix)]
{
use std::fs::Permissions;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use uucore::safe_copy::{create_dest_restrictive, open_source};
let src_file = open_source(from, /* nofollow */ true)
.map_err(|err| io::Error::new(err.kind(), translate!("mv-error-permission-denied")))?;
let src_mode = src_file
.metadata()
.map_err(|err| io::Error::new(err.kind(), translate!("mv-error-permission-denied")))?
.mode()
& 0o7777;
let mut dst_file = create_dest_restrictive(to, /* nofollow */ true)
.map_err(|err| io::Error::new(err.kind(), translate!("mv-error-permission-denied")))?;
uucore::buf_copy::copy_fast(&mut &src_file, &mut dst_file)
.map_err(|err| io::Error::new(err.kind(), translate!("mv-error-permission-denied")))?;
#[cfg(not(any(target_vendor = "apple", target_os = "redox")))]
{
let _ = fsxattr::copy_xattrs_fd_ignore_unsupported(&src_file, &dst_file);
}
// chown before chmod: chown(2) clears setuid/setgid for non-root,
// so the final mode must be applied last to preserve those bits.
//View on GitHub (pinned to 85295bbf78)
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).
Example fix
// before mv /secure/id_rsa /mnt/usb/ // mode 0600, other user // after sudo mv /secure/id_rsa /mnt/usb/ && sudo chown $(id -u) /mnt/usb/id_rsa
Defensive patterns
Strategy: validation
Validate before calling
fn can_read_source(p: &Path) -> bool {
std::fs::File::open(p).is_ok() // or check mode bits on unix
}
if !can_read_source(from) { eprintln!("no read access to {}", from.display()); } Type guard
fn readable(p: &Path) -> bool {
use std::os::unix::fs::PermissionsExt;
std::fs::metadata(p).map(|m| m.mode() & 0o444 != 0).unwrap_or(false)
} Try / catch
match mv_result {
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
// advise chmod/chown or sudo; same-device rename still possible
}
r => r?,
} Prevention
- 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
When it happens
Trigger: `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).
Common situations: 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.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- mv-error-inter-device-move-failed
- mv-error-dangling-symlink
- mv-error-dest-appeared
- Is a directory
- Too many levels of symbolic links
AI-assisted analysis of uutils/coreutils@85295bbf78 (2026-08-31).
Data as JSON: /api/errors/79605d521358c27c.
Report an issue: GitHub.