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

  1. Verify the symlink's target exists before moving: `readlink <link>` / `fs::read_link` and check the target path.
  2. Recreate the symlink manually at the destination (`ln -s <target> <dest>`) and delete the source, bypassing the fallback.
  3. If the dangling link is unwanted, delete it with `rm` instead of `mv`.
  4. 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

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


AI-assisted analysis of uutils/coreutils@85295bbf78 (2026-08-31). Data as JSON: /api/errors/f5b467aa98daa2e9. Report an issue: GitHub.