Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Linux Admins By James Joyner IV · · 8 min read Last reviewed Jul 2026

Linux Error Guide: 'No such file or directory' — Fix a Broken Symlink

Quick answer

Fix a broken symbolic link on Linux: detect dangling links with ls, readlink and find -xtype l, understand relative vs absolute targets, and recreate the link safely with ln -sfn.

  • #linux
  • #troubleshooting
  • #errors
  • #filesystem
Free toolkit

Stuck on this Linux Admins error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

Overview

A broken (dangling) symbolic link is one of the more confusing Linux errors because the link itself clearly exists — you can see it in ls — yet every attempt to use it fails with a “not found” error:

$ cat /etc/nginx/sites-enabled/app.conf
cat: /etc/nginx/sites-enabled/app.conf: No such file or directory

The file appears to be right there, so the message feels like a lie. What Linux is really telling you is that the target the symlink points to no longer exists. The link is a signpost, and the destination it names has been deleted, moved, or renamed. Following the signpost lands on nothing, so the kernel returns ENOENT — the same “No such file or directory” you would get for a file that was never created.

Symptoms

  • ls shows the link, but cat, open, or a service that reads it fails with “No such file or directory”.
  • ls -l colours the link red (on most terminals) and points at a target that is not there.
  • A service like nginx, systemd, or a language runtime reports a missing config or library that “should” exist.
  • test -e <link> returns false even though test -L <link> returns true.
  • Copying or moving a directory tree left links pointing at old absolute paths.

Common Root Causes

  • The target was deleted or renamed after the link was created.
  • A relative link was created from the wrong directory, so its relative path resolves to nowhere.
  • An absolute link broke after a move — the tree was relocated but the link still points at the original absolute path.
  • A versioned target changed — for example a current -> release-2024-01 link whose release directory was pruned.
  • A packaging or deploy step ran out of order, creating the link before (or after) the file it references.
  • Cross-filesystem assumptions — a link created inside a container or chroot that points outside it.

Diagnostic Workflow

Start with a long listing. ls -l shows exactly where the link points, which is the fastest way to spot an obviously wrong target:

ls -l /etc/nginx/sites-enabled/app.conf
# lrwxrwxrwx 1 root root 38 Jul  5 09:12 app.conf -> ../sites-available/app.conf

Resolve the link fully. readlink shows the immediate target; readlink -f (or -e) resolves the whole chain and, with -e, prints nothing if the final target does not exist:

readlink /etc/nginx/sites-enabled/app.conf        # immediate target only
readlink -f /etc/nginx/sites-enabled/app.conf     # canonical resolved path
readlink -e /etc/nginx/sites-enabled/app.conf     # empty output = target missing

Ask the kernel directly whether the resolved target exists. test -e follows the link and checks the destination; test -L checks that the link file itself exists:

test -e /etc/nginx/sites-enabled/app.conf && echo "target OK" || echo "DANGLING"
file /etc/nginx/sites-enabled/app.conf
# app.conf: broken symbolic link to ../sites-available/app.conf

Sweep an entire directory tree for every broken link at once. find -xtype l matches symlinks whose target type cannot be determined — i.e. dangling links:

find /etc/nginx -xtype l
find /opt/app -xtype l -printf '%p -> %l\n'   # show link and its dead target

Example Root Cause Analysis

A deploy switched an application to a new release directory and nginx refused to reload with “No such file or directory” for sites-enabled/app.conf. ls -l revealed the link resolved to ../sites-available/app.conf, and readlink -e returned nothing, confirming a dangling link.

The root cause was a relative target combined with a move: the release script had recreated sites-available/ under a new timestamped path but the enabled link still pointed at the old relative location, which no longer existed after the previous release was pruned. Because the link used a relative path, readlink -f showed the canonical target sitting outside the current release tree.

The fix was to recreate the link atomically with ln -sfn, which forces replacement (-f) and treats the link as a plain name rather than dereferencing an existing directory link (-n):

ln -sfn /etc/nginx/sites-available/app.conf /etc/nginx/sites-enabled/app.conf
readlink -e /etc/nginx/sites-enabled/app.conf   # now prints the real path
nginx -t && systemctl reload nginx

Prevention Best Practices

  • Prefer absolute targets for links that must survive the directory being moved; prefer relative targets for links inside a self-contained tree you expect to relocate as a unit.
  • Recreate links with ln -sfn rather than rm + ln so the swap is atomic and never leaves a window with no link at all.
  • After any deploy or cleanup, run find <dir> -xtype l to catch dangling links before a service does.
  • Prune old release directories after repointing “current”-style links, never before.
  • When copying trees, use cp -a or rsync -a to preserve links, and verify with readlink -e afterwards.

Quick Command Reference

ls -l <link>                     # see the link's declared target
readlink <link>                  # immediate target
readlink -e <link>               # empty output = dangling
test -e <link> && echo OK        # does the target exist?
file <link>                      # reports "broken symbolic link"
find <dir> -xtype l              # list every broken link in a tree
ln -sfn <target> <link>          # atomically (re)create the link

Conclusion

A broken symlink is not a corrupted file — it is a valid link whose target vanished, which is why ls shows it while cat fails with “No such file or directory”. readlink -e and find -xtype l turn the invisible problem into an obvious one, and ln -sfn fixes it atomically. Choose absolute or relative targets deliberately based on whether the tree will move, and sweep for dangling links after every deploy. For more Linux troubleshooting, see the Linux admin guides.

Free download · 368-page PDF

Fixed it? Get 500 Linux Admins & DevOps AI prompts — free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.