denoland/deno · error · NodeSystemError
ERR_FS_CP_DIR_TO_NON_DIR
ERR_FS_CP_DIR_TO_NON_DIR
Error message
Cannot overwrite non-directory with directory
What it means
ERR_FS_CP_DIR_TO_NON_DIR is thrown by throwCpError when the native cp validation reports kind 'DIR_TO_NON_DIR': the source is a directory but the existing destination is a non-directory (a file), so the copy would have to overwrite a file with a directory tree, which fs.cp refuses.
Source
Thrown at ext/node/polyfills/_fs/cp/cp.ts:68
const {
Number,
PromiseResolve,
SymbolAsyncIterator,
} = primordials;
function throwCpError(err) {
const { EEXIST, EINVAL, EISDIR, ENOTDIR } = lazyConstants();
switch (err.kind) {
case "EINVAL":
throw new ERR_FS_CP_EINVAL({
message: err.message,
path: err.path,
syscall: "cp",
errno: EINVAL,
code: "EINVAL",
});
case "DIR_TO_NON_DIR":
throw new ERR_FS_CP_DIR_TO_NON_DIR({
message: err.message,
path: err.path,
syscall: "cp",
errno: EISDIR,
code: "EISDIR",
});
case "NON_DIR_TO_DIR":
throw new ERR_FS_CP_NON_DIR_TO_DIR({
message: err.message,
path: err.path,
syscall: "cp",
errno: ENOTDIR,
code: "ENOTDIR",
});
case "EEXIST":
throw new ERR_FS_CP_EEXIST({
message: err.message,
path: err.path,View on GitHub (pinned to 89f33cbef2)
Solutions
- Remove or rename the existing file at dest first (fs.rm(dest, { force: true }))
- Point dest at a directory path that does not currently exist as a file
- If automated, pre-stat dest and clean conflicting non-directories before copying
Example fix
// before
await fsp.cp(srcDir, destPath, { recursive: true }); // destPath is an existing file
// after
const st = await fsp.lstat(destPath).catch(() => null);
if (st && !st.isDirectory()) await fsp.rm(destPath, { force: true });
await fsp.cp(srcDir, destPath, { recursive: true }); Defensive patterns
Strategy: validation
Validate before calling
const st = await fsp.lstat(dest).catch(() => null);
if (st && !st.isDirectory()) await fsp.rm(dest, { force: true });
await fsp.cp(src, dest, { recursive: true }); Type guard
async function isDir(p) { try { return (await fsp.lstat(p)).isDirectory(); } catch { return false; } } Try / catch
try { await fsp.cp(src, dest, { recursive: true }); } catch (e) { if (e.code === 'ERR_FS_CP_DIR_TO_NON_DIR') { await fsp.rm(dest, { force: true }); await fsp.cp(src, dest, { recursive: true }); } else throw e; } Prevention
- Pre-stat dest before directory copies and clear non-directory conflicts
- Keep build outputs type-stable per path across runs
- In deploy scripts, clean stale artifacts at conflicting paths
When it happens
Trigger: await fsp.cp('./src', './src.txt', { recursive: true }) where src is a directory and src.txt an existing regular file; deploying a directory over a stale file left at the destination path.
Common situations: Build outputs where an earlier run produced a file and a later run produces a directory at the same path; wrong CLI arg order swapping a file dest and dir src.
Related errors
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/61a5d2c684424f71.
Report an issue: GitHub.