Skip to content

fs: calling mkdir in fs.cp function can ignore EEXIST error - #53534

Closed
ShenHongFei wants to merge 2 commits into
nodejs:mainfrom
ShenHongFei:fs-cp-mkdir-ignore-eexist
Closed

ShenHongFei wants to merge 2 commits into
nodejs:mainfrom
ShenHongFei:fs-cp-mkdir-ignore-eexist

Conversation

@ShenHongFei

Copy link
Copy Markdown
Contributor

This PR mainly aims to solve the following problem. During the execution of the fsp.cp function, due to other file operations, the target directory of fsp.cp is created in parallel. The actual situation may be more complicated. Multiple file operations are executed concurrently, resulting in an error in the internal fsp.cp when calling mkdir, because the folder has been created by other file operations. In this case, you can actually ignore this error and continue with the subsequent file copying operation.

import { promises as fsp } from 'fs'

const src = 'T:/src/'
const dst = 'T:/out/'

try {
    await fsp.rm(dst, { recursive: true })
} catch { }

await Promise.all([
    fsp.cp(src, dst, {
        recursive: true,
        force: true,
        errorOnExist: false,
        mode: 0
    }),
    
    // example other file operations in parallel
    fsp.mkdir(dst, { recursive: true })
])

// throws EEXIST: file already exists, mkdir 'T:/out/'
// at mkdir()
// at mkDirAndCopy() lib/internal/fs/cp/cp.js
// at onDir() lib/internal/fs/cp/cp.js

The relevant code is in lib/internal/fs/cp/cp.js.
destStat is empty here, it did not exist when checking the folder before.

function onDir(srcStat, destStat, src, dest, opts) {
  if (!destStat) return mkDirAndCopy(srcStat.mode, src, dest, opts);
  return copyDir(src, dest, opts);
}

async function mkDirAndCopy(srcMode, src, dest, opts) {
  await mkdir(dest);
  await copyDir(src, dest, opts);
  return setDestMode(dest, srcMode);
}

I want to ignore the EEXIST error thrown by mkdir

async function mkDirAndCopy(srcMode, src, dest, opts) {
  try {
    await mkdir(dest);
  } catch (error) {
    // If the folder already exists, skip it.
    if (error.code !== 'EEXIST')
      throw error;
  }

  await copyDir(src, dest, opts);
  return setDestMode(dest, srcMode);
}

@nodejs-github-bot nodejs-github-bot added fs Issues and PRs related to file-system APIs and the fs module. needs-ci PRs that need a full CI run. labels Jun 21, 2024
Comment thread lib/internal/fs/cp/cp.js Outdated
await mkdir(dest);
} catch (error) {
// If the folder already exists, skip it.
if (error.code !== 'EEXIST')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pull-request needs a test.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a test and adjusted it to ignore this error only when the errorOnExist parameter is false

@ShenHongFei
ShenHongFei requested a review from anonrig June 24, 2024 04:31
@ShenHongFei
ShenHongFei force-pushed the fs-cp-mkdir-ignore-eexist branch from 3ae92fb to 5659000 Compare June 24, 2024 05:43
@ShenHongFei

Copy link
Copy Markdown
Contributor Author

@anonrig I added a test and changed the logic to ignore the error only when the errorOnExist parameter is false. What else do I need to do? Can you take another look?

Comment thread lib/internal/fs/cp/cp.js
Comment on lines +309 to +315
try {
await mkdir(dest);
} catch (error) {
// If the folder already exists, skip it.
if (error.code === 'EEXIST' && !opts.errorOnExist); else
throw error;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When set to recursive, it will automatically ignore the EEXIST error. And the situation that needs to consider force.

Suggested change
try {
await mkdir(dest);
} catch (error) {
// If the folder already exists, skip it.
if (error.code === 'EEXIST' && !opts.errorOnExist); else
throw error;
}
await mkdir(dest, {
recursive: opts.force || !opts.errorOnExist
});

@BlackHole1

Copy link
Copy Markdown

PTAL @anonrig. I just encountered the same issue. When using fs.cp in a concurrent situation, this bug occurs.

BlackHole1 added a commit to oomol-lab/oopm that referenced this pull request Feb 12, 2025
When installing duplicated dependencies, it triggers concurrency issues in Node.js (see: nodejs/node#53534).

This can be avoided by pre-deduplication.

Signed-off-by: Kevin Cui <bh@bugs.cc>
l1shen pushed a commit to oomol-lab/oopm that referenced this pull request Feb 12, 2025
When installing duplicated dependencies, it triggers concurrency issues
in Node.js (see: nodejs/node#53534).

This can be avoided by pre-deduplication.

Signed-off-by: Kevin Cui <bh@bugs.cc>
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.

@github-actions github-actions Bot added the stale Issues and PRs marked stale due to inactivity and scheduled for automatic closure. label Jul 28, 2026
@avivkeller avivkeller closed this Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fs Issues and PRs related to file-system APIs and the fs module. needs-ci PRs that need a full CI run. stale Issues and PRs marked stale due to inactivity and scheduled for automatic closure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants