Fix 'ln: failed to create symbolic link: File exists' on Linux

beginner๐Ÿง Linux2026-05-06| Linux (Ubuntu, Debian, CentOS, Arch) โ€” any shell using ln command

Error Message

ln: failed to create symbolic link '/usr/local/bin/node': File exists
#ln#symlink#symbolic-link#filesystem

The Error

ln: failed to create symbolic link '/usr/local/bin/node': File exists

You ran ln -s to create a symlink and hit this wall. Something is already sitting at that target path โ€” a file, a directory, or a stale symlink pointing nowhere. ln won't overwrite it unless you explicitly tell it to.

Why This Happens

The destination path (/usr/local/bin/node here) is already occupied. A few common ways you end up here:

  • You installed the same tool twice via different methods โ€” nvm alongside the system package manager, for instance
  • A leftover symlink from an older installation is still hanging around
  • A setup script re-ran without cleaning up first
  • A real binary โ€” not a symlink โ€” is already at that exact path

Step 1 โ€” Check What's Already There

Don't touch anything yet. First figure out what you're dealing with:

ls -la /usr/local/bin/node

Three things you might see:

# A valid symlink pointing somewhere good
lrwxrwxrwx 1 root root 30 Mar 12 2024 /usr/local/bin/node -> /home/user/.nvm/versions/node/v20.0.0/bin/node

# A broken symlink (target was deleted)
lrwxrwxrwx 1 root root 30 Mar 12 2024 /usr/local/bin/node -> /home/user/.nvm/versions/node/v18.0.0/bin/node

# An actual binary
-rwxr-xr-x 1 root root 89654312 Jan 5 10:22 /usr/local/bin/node

For symlinks, verify the target still exists:

readlink -f /usr/local/bin/node

Empty output or a path that doesn't exist? The symlink is broken. Safe to replace.

Step 2 โ€” Force-Overwrite With -sf

Fastest fix: the -f flag removes whatever is there and creates the new symlink in one go.

ln -sf /path/to/new/target /usr/local/bin/node

-s = symbolic, -f = force overwrite. Concrete example with nvm Node v20.11.0:

ln -sf /home/user/.nvm/versions/node/v20.11.0/bin/node /usr/local/bin/node

Need root? Prefix with sudo:

sudo ln -sf /home/user/.nvm/versions/node/v20.11.0/bin/node /usr/local/bin/node

Step 3 โ€” Manual Remove Then Relink (When -f Falls Short)

There's one case where -f won't save you: when the target is a directory. Remove it manually first.

# Confirm what type it is
file /usr/local/bin/node

# Remove the file or symlink
sudo rm /usr/local/bin/node

# Now create the symlink
sudo ln -s /path/to/target /usr/local/bin/node

If it's a directory, use the right removal command:

# Empty directory
sudo rmdir /usr/local/bin/node

# Non-empty directory (double-check before running this)
sudo rm -r /usr/local/bin/node

sudo ln -s /path/to/target /usr/local/bin/node

Step 4 โ€” Verify the Fix

Three quick checks to confirm everything is wired up correctly:

ls -la /usr/local/bin/node
readlink -f /usr/local/bin/node
node --version

All three should agree. Expected output:

lrwxrwxrwx 1 root root 52 May  5 02:14 /usr/local/bin/node -> /home/user/.nvm/versions/node/v20.11.0/bin/node
/home/user/.nvm/versions/node/v20.11.0/bin/node
v20.11.0

Dealing With Two Installations Competing for the Same Path

nvm and apt both want to own /usr/local/bin/node. They'll keep stepping on each other. The clean solution: pick one and remove the other.

# Ubuntu/Debian โ€” remove the system package
sudo apt remove nodejs

# CentOS/RHEL
sudo dnf remove nodejs

Let nvm take over from there. Alternatively, keep the system package and repoint the symlink to wherever it installed the binary:

which node   # Find where the system binary actually lives
sudo ln -sf $(which node) /usr/local/bin/node

Cleaning Up Multiple Broken Symlinks at Once

Botched install script? There might be more than one broken symlink to deal with. Find them all first:

# List every broken symlink in /usr/local/bin
find /usr/local/bin -maxdepth 1 -type l ! -exec test -e {} \; -print

Review the list before removing anything. Then repoint or delete as needed.

Preventing This From Happening Again

  • Default to -sf in scripts, not bare -s. It's idempotent โ€” re-running the script won't blow up on an existing link.
  • Guard before linking: add [ -e "$target" ] && rm "$target" before the ln call in install scripts.
  • One package manager per tool. Mixing nvm + apt for Node (or pyenv + pip for Python) is how you end up back here.
  • On Debian-based systems, use update-alternatives for tools with multiple versions โ€” it handles symlink management so you don't have to:
sudo update-alternatives --install /usr/bin/node node /usr/local/bin/node 100

Related Error Notes