uutils/coreutils · error · io::Error
invalid destination path
Error message
invalid destination path
What it means
In the symlink-replacement fallback, mv derives the destination's parent and basename via openat-based atomic replacement. If the destination path has no final component (e.g., it is '.' , '..' , '/' or ends in '..'), to.file_name() returns None and this InvalidInput error is raised. It protects the low-level create_symlink_replace logic from a destination it cannot split into dir + name.
Source
Thrown at src/uu/mv/src/mv.rs:1075
#[cfg(all(unix, not(target_os = "redox")))]
fn create_symlink_replace(target: &Path, to: &Path) -> io::Result<()> {
use io::Read;
use rustix::fs::{AtFlags, CWD, Mode, OFlags, openat, renameat, symlinkat, unlinkat};
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;
// GNU's template is `CuXXXXXX`: a 2-char prefix plus 6 random chars
// drawn from a 62-char alphabet. Modulo bias on a 256→62 mapping is
// ~3% per slot — irrelevant for an 8-char unguessability budget.
const ALPHABET: &[u8; 62] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let parent = to
.parent()
.filter(|p| !p.as_os_str().is_empty())
.unwrap_or_else(|| Path::new("."));
let basename = to
.file_name()
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "invalid destination path"))?;
let dir_fd = openat(
CWD,
parent,
OFlags::DIRECTORY | OFlags::RDONLY | OFlags::CLOEXEC | OFlags::NOFOLLOW,
Mode::empty(),
)?;
let mut urandom = fs::File::open("/dev/urandom")?;
for _ in 0..32 {
let mut tmp_bytes = *b"Cu------";
let mut raw = [0u8; 6];
urandom.read_exact(&mut raw)?;
for (slot, byte) in tmp_bytes[2..].iter_mut().zip(raw) {
*slot = ALPHABET[(byte as usize) % ALPHABET.len()];
}
let tmp = OsStr::from_bytes(&tmp_bytes);View on GitHub (pinned to 85295bbf78)
Solutions
- Pass a real destination filename, not '.', '..' or the filesystem root
- Normalize the destination with `realpath`/canonicalize in scripts before invoking mv
- Validate the target in scripts: ensure it has a basename component (e.g., `[ -n "$(basename "$dest")" ]` and dest != . / .. )
- If the intent was 'move into directory', drop -T/--no-target-directory and let mv resolve the dir
Example fix
// before mv -T newlink . // after mv -T newlink /path/to/existing-link-name
Defensive patterns
Strategy: validation
Validate before calling
# ensure destination has a basename and is not '.' / '..' / '/' case "$dest" in ""|"."|".."|"/"|".") echo "invalid destination path"; exit 1;; esac case "$dest" in *[!/]*/) echo "trailing slash on non-dir target" ;; esac
Try / catch
null
Prevention
- Validate path variables with realpath/canonicalize before mv
- Reject destinations without a filename component in scripts
- Be careful combining -T with directory-valued targets
When it happens
Trigger: Calling mv with a symlink destination that is a bare directory reference like `mv -T link .`, `mv src ..`, `mv src /`, or a trailing path that normalizes to a directory with no filename.
Common situations: Scripts building destination paths from variables that end up empty or as '.'/'..'; typos with trailing slashes or dot components; using mv -T with directory-valued targets.
Related errors
- could not allocate a unique temp name in destination directo
- mv-error-dangling-symlink
- mv-error-inter-device-move-failed
- Too many levels of symbolic links
- Too many levels of symbolic links
AI-assisted analysis of uutils/coreutils@85295bbf78 (2026-08-31).
Data as JSON: /api/errors/839506a9099b34f7.
Report an issue: GitHub.