denoland/deno · error · NodeSystemError
ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY
ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY
Error message
Cannot overwrite symlink in subdirectory of self
What it means
ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY ('Cannot overwrite symlink in subdirectory of self') is thrown for kind 'SYMLINK_TO_SUBDIRECTORY': with dereference:true, the resolved destination lands inside the source tree (dest is a subdirectory of src), so continuing would make cp copy a directory into itself. It is the same guard Node uses to prevent infinite recursive copies.
Source
Thrown at ext/node/polyfills/_fs/cp/cp.ts:124
});
case "FIFO":
throw new ERR_FS_CP_FIFO_PIPE({
message: err.message,
path: err.path,
syscall: "cp",
errno: EINVAL,
code: "EINVAL",
});
case "UNKNOWN":
throw new ERR_FS_CP_UNKNOWN({
message: err.message,
path: err.path,
syscall: "cp",
errno: EINVAL,
code: "EINVAL",
});
case "SYMLINK_TO_SUBDIRECTORY":
throw new ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY({
message: err.message,
path: err.path,
syscall: "cp",
errno: EINVAL,
code: "EINVAL",
});
default:
throw err;
}
}
async function cpFn(
src,
dest,
opts,
) {
try {
if (canUseNativeFastPath(opts)) {View on GitHub (pinned to 89f33cbef2)
Solutions
- Choose a destination outside the source tree
- Or set dereference:false / verbatimSymlinks as appropriate so dest resolution does not fold into src
- Guard with path.relative: if the result doesn't start with '..' and isn't '', dest is inside src — reject before copying
Example fix
// before
await fsp.cp(src, path.join(src, 'dist/backup'), { recursive: true, dereference: true });
// after
const dest = path.join(rootOutsideSrc, 'backup');
await fsp.cp(src, dest, { recursive: true, dereference: true }); Defensive patterns
Strategy: validation
Validate before calling
const rel = path.relative(path.resolve(src), path.resolve(dest));
const destInsideSrc = rel !== '' && !rel.startsWith('..');
if (destInsideSrc) throw new Error('dest must not be inside src when dereference is enabled'); Type guard
function isDestInsideSrc(src, dest) {
const rel = path.relative(path.resolve(src), path.resolve(dest));
return rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
} Try / catch
try { await fsp.cp(src, dest, { recursive: true, dereference: true }); } catch (e) { if (e.code === 'ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY') throw new Error(`dest ${dest} is inside src ${src}`); throw e; } Prevention
- Place outputs outside the source tree
- Check path.relative(src, dest) before recursive copies with dereference
- Prefer dereference:false when you only need to preserve symlinks
When it happens
Trigger: await fsp.cp('/data/project', '/data/project/sub/copy', { recursive: true, dereference: true }); copying a folder into a nested folder of itself; build tools writing output into an input subfolder while following symlinks.
Common situations: Out-of-tree output paths misconfigured to live under the source tree; monorepo scripts whose dest is computed relative to src and ends up nested.
Related errors
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/afadfc2198643b75.
Report an issue: GitHub.