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

  1. Pick matching kinds: copy files onto file paths, directories (with recursive) onto directory paths
  2. If the old directory is stale, remove it first: fs.rm(dest, { recursive: true, force: true })
  3. 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

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)