uutils/coreutils · error · io::Error
mv-error-dangling-symlink
Error message
mv-error-dangling-symlink
What it means
Raised by mv's rename_symlink_fallback (Windows path) when it must recreate a symlink at the destination but the source symlink itself is dangling — its target cannot be resolved, so `path_symlink_points_to` is None and mv refuses to guess. Instead of silently copying a broken link, it returns an io::Error with kind NotFound carrying this localized message. mv only reaches this fallback after a plain rename failed (e.g. cross-device), so the error surfaces mid-move.
Source
Thrown at src/uu/mv/src/mv.rs:1124
}
Err(io::Error::new(
io::ErrorKind::AlreadyExists,
"could not allocate a unique temp name in destination directory",
))
}
#[cfg(windows)]
fn rename_symlink_fallback(from: &Path, to: &Path) -> io::Result<()> {
let path_symlink_points_to = fs::read_link(from)?;
if path_symlink_points_to.exists() {
if path_symlink_points_to.is_dir() {
windows::fs::symlink_dir(&path_symlink_points_to, to)?;
} else {
windows::fs::symlink_file(&path_symlink_points_to, to)?;
}
fs::remove_file(from)
} else {
Err(io::Error::new(
io::ErrorKind::NotFound,
translate!("mv-error-dangling-symlink"),
))
}
}
#[cfg(target_os = "wasi")]
fn rename_symlink_fallback(_from: &Path, _to: &Path) -> io::Result<()> {
Err(io::Error::other(translate!("mv-error-no-symlink-support")))
}
fn rename_dir_fallback(
from: &Path,
to: &Path,
display_manager: Option<&MultiProgress>,
verbose: bool,
#[cfg(unix)] hardlink_tracker: Option<&mut HardlinkTracker>,
#[cfg(unix)] hardlink_scanner: Option<&HardlinkGroupScanner>,View on GitHub (pinned to 85295bbf78)
Solutions
- Verify the symlink's target exists before moving: `readlink <link>` / `fs::read_link` and check the target path.
- Recreate the symlink manually at the destination (`ln -s <target> <dest>`) and delete the source, bypassing the fallback.
- If the dangling link is unwanted, delete it with `rm` instead of `mv`.
- On Windows, ensure Developer Mode / symlink privileges are available and the target drive is mounted so resolution succeeds.
Example fix
// before mv -f /mnt/a/link /mnt/b/link // cross-device, dangling target -> NotFound // after target=$(readlink /mnt/a/link); [ -e "$target" ] || ln -s "$target" /mnt/b/link && rm /mnt/a/link
Defensive patterns
Strategy: validation
Validate before calling
let target = std::fs::read_link(link)?;
if !target.exists() {
eprintln!("dangling symlink: {} -> {}", link.display(), target.display());
// remove instead of move, or fix target first
} Type guard
fn is_dangling(link: &Path) -> bool {
link.symlink_metadata().map(|m| m.is_symlink()).unwrap_or(false)
&& link.metadata().is_err()
} Try / catch
match mv_result {
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
// dangling symlink: handle/remove explicitly
}
r => r?,
} Prevention
- Check read_link + target existence before moving symlinks
- Clean up dangling links with a periodic find -xtype l sweep
- Avoid cross-device moves of symlinks; move targets and relink instead
When it happens
Trigger: Calling `mv` on a symbolic link whose target does not exist, on a code path where the fast rename failed (cross-device move) and the fallback must reconstruct the link; on Windows the target resolution via symlink metadata returns None, hitting the else branch that constructs this error.
Common situations: Moving a symlink left behind by a deleted/uninstalled target; moving symlinks between filesystems where rename returns EXDEV; build or tmpfs setups where link targets live on another mount; Windows developer environments with NTFS symlinks whose targets were removed.
Related errors
- mv-error-inter-device-move-failed
- Too many levels of symbolic links
- invalid destination path
- could not allocate a unique temp name in destination directo
- mv-error-dest-appeared
AI-assisted analysis of uutils/coreutils@85295bbf78 (2026-08-31).
Data as JSON: /api/errors/f5b467aa98daa2e9.
Report an issue: GitHub.