This error occurs when Node.js attempts to resolve a symbolic link to its actual target using fs.realpath() or fs.realpathSync(), but the symlink points to a non-existent file or directory. This typically indicates a broken symlink in your project.
This error is raised by the `fs.realpath()` or `fs.realpathSync()` functions in Node.js when they try to follow a symbolic link to its actual target, but the target doesn't exist on the file system. The `realpath` function is used to resolve a path to its absolute, canonical form by following symbolic links and normalizing the path (handling `.`, `..`, and extra slashes). When a symlink points to a non-existent location, the function cannot complete the resolution and throws an ENOENT (No such file or directory) error. This commonly happens when: - A symlink was created but the target file was moved or deleted - A symlink points to a path that's only valid on another system or environment - Dependencies or build artifacts referenced by symlinks have been cleaned up - Module resolution encounters a broken symlink in node_modules or in your project structure
First, determine which file or directory is the broken symlink. The error message usually shows the path. Run the following commands to find and examine the symlink:
# List the symlink and see where it points
ls -la path/to/symlink
# See the target of the symlink
readlink path/to/symlink
# Check if the target exists
ls -la $(readlink path/to/symlink)The symlink is broken if the readlink output points to a path that doesn't exist. For example:
$ ls -la src/lib
lrwxr-xr-x 1 user group 25 Dec 1 10:30 config -> ../../config/missing
$ readlink src/lib/config
../../config/missing
$ ls -la ../../config/missing
ls: cannot access '../../config/missing': No such file or directoryOnce you've confirmed the symlink is broken, remove it using the rm command. Be careful to specify the symlink path, not the target:
# Remove the broken symlink
rm path/to/symlink
# Verify it's gone
ls path/to/symlink # Should show "No such file or directory"Important: This removes only the symlink, not the target it pointed to. Since the target doesn't exist anyway, this is safe.
To remove all broken symlinks in a directory tree, use find:
# Find all broken symlinks in current directory
find . -type l ! -exec test -e {} \; -print
# Remove all broken symlinks
find . -type l ! -exec test -e {} \; -deleteIf the symlink should exist (it's intentional), create it again pointing to the correct target. First, figure out where it should point:
# Remove the old broken symlink
rm path/to/symlink
# Create a new symlink with the correct target
ln -s /path/to/actual/target path/to/symlink
# Verify the symlink works
ls -la path/to/symlink
readlink path/to/symlinkExample: If you have a symlink that should point to a config file:
# Broken symlink points to non-existent file
$ ls -la src/config
lrwxr-xr-x 1 user group 25 Dec 1 config -> ../../configs/app.json
$ readlink src/config
../../configs/app.json # This path doesn't exist
# Fix it by creating a symlink to the actual location
rm src/config
ln -s ../../config/app.json src/config
# Verify it works
ls src/config # Should show the content of the actual fileIf the error occurs during module import or require, the broken symlink might be in your node_modules directory. This often happens with linked packages or dependency issues:
# Find broken symlinks in node_modules
find node_modules -type l ! -exec test -e {} \; -print
# Clean and reinstall dependencies
rm -rf node_modules package-lock.json
npm installFor projects using npm workspaces or npm link:
# List all linked packages
npm ls -g --depth=0 --link
# Unlink broken packages
npm unlink package-name
# Re-link if still needed
npm link /path/to/packageFor Yarn projects:
# Clear cache and reinstall
rm -rf node_modules yarn.lock
yarn installIf you're using fs.realpath() or fs.realpathSync() in your code, add proper error handling to deal with broken symlinks gracefully:
// Using async realpath with error handling
const fs = require('fs').promises;
async function resolvePath(filePath) {
try {
const realPath = await fs.realpath(filePath);
console.log(`Real path: ${realPath}`);
return realPath;
} catch (error) {
if (error.code === 'ENOENT') {
console.error(`Symlink is broken: ${filePath}`);
console.error(`Target does not exist: ${error.path}`);
// Handle broken symlink - maybe delete it or log for cleanup
} else {
throw error;
}
}
}// Using sync realpath with error handling
const fs = require('fs');
function resolvePath(filePath) {
try {
const realPath = fs.realpathSync(filePath);
console.log(`Real path: ${realPath}`);
return realPath;
} catch (error) {
if (error.code === 'ENOENT') {
console.error(`Cannot resolve symlink ${filePath}`);
// Handle the broken symlink appropriately
return null;
} else {
throw error;
}
}
}// Check if symlink exists before resolving
const fs = require('fs');
function safeRealpath(filePath) {
if (!fs.existsSync(filePath)) {
console.error(`Symlink does not exist: ${filePath}`);
return null;
}
try {
return fs.realpathSync(filePath);
} catch (error) {
console.error(`Failed to resolve symlink: ${error.message}`);
return null;
}
}Symlink Chains:
Symlinks can point to other symlinks, creating chains. Node.js follows the entire chain until it reaches a real file or directory, or encounters a broken link at any point. If any symlink in the chain points to a non-existent target, the entire resolution fails:
# Chain: symlink -> symlink -> non-existent file
link1 -> link2
link2 -> non-existent-file
# This fails because the chain is broken
fs.realpath('link1') # ENOENT errorPlatform-Specific Issues:
Symlinks behave differently across operating systems:
- Linux/macOS: Symlinks work transparently and can be relative or absolute
- Windows: Symlinks require admin privileges and may not work as expected with NTFS junctions
- WSL (Windows Subsystem for Linux): Symlinks pointing to Windows paths may break if accessed from different subsystems
Circular Symlinks:
Although not usually the cause of ENOENT, be aware that circular symlinks (A -> B, B -> A) will cause issues:
ln -s b a
ln -s a b
# This creates infinite loop
fs.realpath('a') # Hangs or fails depending on OSNode.js Caching Behavior:
fs.realpath() can accept a cache object to improve performance when resolving multiple paths. However, if the file system changes after populating the cache, the cached entries become stale:
const cache = {};
// First call populates cache
const path1 = fs.realpathSync('link1', cache);
// If symlink is deleted between calls, cache still has old entry
// You may need to clear cache if file system changes
fs.realpath('link2', { cache }, (err, path) => { });
// Clear cache on error or periodically
Object.keys(cache).forEach(key => delete cache[key]);Using realpath.native():
Node.js provides fs.realpath.native() which uses the operating system's native path resolution. This can behave differently from the JavaScript implementation:
const fs = require('fs');
// JavaScript implementation (slower but consistent)
fs.realpath(path, (err, resolved) => { });
// Native OS implementation (faster, platform-specific)
fs.realpath.native(path, (err, resolved) => { });Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams