denoland/deno · error · SystemError
ERR_FS_CP_NON_DIR_TO_DIR
ERR_FS_CP_NON_DIR_TO_DIR
Error message
Cannot overwrite directory with non-directory
What it means
The mirror case of DIR_TO_NON_DIR: fs.cp stats both paths and, when src is a non-directory (a file, socket, etc.) while an existing dest is a directory, rejects with kind NON_DIR_TO_DIR. throwCpError maps it to ERR_FS_CP_NON_DIR_TO_DIR ('Cannot overwrite directory with non-directory', errno ENOTDIR). Overwriting a directory with a single file is not a defined copy operation, so it fails before any transfer.
Solutions
- Pick matching kinds: copy files onto file paths, directories (with recursive) onto directory paths
- If the old directory is stale, remove it first: fs.rm(dest, { recursive: true, force: true })
- Validate with fs.stat before copying and fail fast with a clear message
Example fix
// before
fs.cp('bundle.js', 'out/', cb); // 'out' is an existing directory
// after
fs.cp('bundle.js', 'out/bundle.js', cb);
// or clear the stale directory first
fs.rmSync('out', { recursive: true, force: true });
fs.cp('bundle.js', 'out', cb); Defensive patterns
Strategy: try-catch
Validate before calling
const st = fs.statSync(dest, { throwIfNoEntry: false });
if (st?.isDirectory()) throw new Error('cp: dest is a directory but src is a file'); Try / catch
try { fs.copyFileSync(src, dest); } catch (e) { if (e.code === 'ERR_FS_CP_NON_DIR_TO_DIR') { fs.rmSync(dest, { recursive: true }); fs.copyFileSync(src, dest); } else throw e; } Prevention
- Match artifact kind to layout: bundles are files, folders are folders
- Remove old build trees when the artifact shape changes
- Check dest with lstat when symlinks may be involved
When it happens
Trigger: fs.cp('notes.txt', 'notes/') where 'notes' is an existing directory; forgetting { recursive: true } is NOT the fix here — the src/dest kinds simply conflict; deploy pipelines copying a versioned file (app.js) onto a directory path that a previous layout created.
Common situations: Changing artifact layout from a directory to a single bundled file without cleaning old builds; trailing-slash confusion where the dest directory already exists; templates that create directory skeletons later targeted by file copies.
Related errors
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/6c7a79dd289a7a15.
Report an issue: GitHub.
Appendix: source
Thrown at ext/node/polyfills/_fs/cp/cp.ts:76
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,
syscall: "cp",
errno: EEXIST,
code: "EEXIST",
});
case "EISDIR":
throw new ERR_FS_EISDIR({
message: err.message,
path: err.path,View on GitHub (pinned to 9ad36f7a2c)