Node-fs-extra: Multiple fse.copy throw EEXIST error

Created on 27 Jun 2019  ยท  4Comments  ยท  Source: jprichardson/node-fs-extra


  • Operating System: MacOSx 10.14.5
  • Node.js version: 10.16.0
  • fs-extra version: 8.0.1

When I use Promise.all with multiple fse.copy, if the destination directory doesn't exist, it will throw an EEXIST error

const fse = require("fs-extra");

Promise.all([fse.copy("from-2", "to"), fse.copy("from-1", "to")]).catch(err =>
  console.log(err)
);
{ [Error: EEXIST: file already exists, mkdir 'to'] errno: -17, code: 'EEXIST', syscall: 'mkdir', path: 'to' }

It seems that the function mkDirAndCopy uses fs.mkdir which leads to the error

function mkDirAndCopy (srcStat, src, dest, opts, cb) {
  fs.mkdir(dest, err => {
    if (err) return cb(err)
    copyDir(src, dest, opts, err => {
      if (err) return cb(err)
      return fs.chmod(dest, srcStat.mode, cb)
    })
  })
}

And I think it may be the same reason for issue#454

Is it possible to replace fs.mkdir with fse.mkdirp or ignore the EEXIST error in this situation?

If it's OK, I will make a PR for this.

question

Most helpful comment

Approached same problem. It's clearly a bug and fs.copy should not crash in such scenarios

What's interesting I was faced with it when migrating to v8 (note v9 also exposes issue) from v0.30 with which there's no such problem.

This bug prevents constructing efficient flows which may intentionally introduce safe race conditions, e.g. I've needed to refactor part of a flow from parallel to consecutive due to that issue: https://github.com/serverless/serverless/commit/548bd986e4dafcae207ae80c3a8c3f956fbce037

All 4 comments

The reason you're getting an error is that you're copying two things, from-1 & from-2 to the same place, to. from-1 & from-2 cannot simultaneously be located at to. I assume you're attempting to copy both from-1 & from-2 _into_ a directory named to, in which case you want:

Promise.all([fse.copy("from-2", "to/from-2"), fse.copy("from-1", "to/from-1")])

The reason you're getting an error is that you're copying two things, from-1 & from-2 to the same place, to. from-1 & from-2 cannot simultaneously be located at to. I assume you're attempting to copy both from-1 & from-2 _into_ a directory named to, in which case you want:

Promise.all([fse.copy("from-2", "to/from-2"), fse.copy("from-1", "to/from-1")])

In fact, I want to copy both the content of from-1 and from-2 into a directory named to, which means if I have a file structure like this

โ”œโ”€โ”€ from-1
โ”‚   โ””โ”€โ”€ 1
โ”œโ”€โ”€ from-2
    โ””โ”€โ”€ 2

I hope the result is

โ””โ”€โ”€ to
    โ”œโ”€โ”€ 1
    โ””โ”€โ”€ 2

I don't know in this case, if my operation is appropriate?

For that, you'll need to fs.readdir from-1 & from-2, and then loop over each item, copying it.

Approached same problem. It's clearly a bug and fs.copy should not crash in such scenarios

What's interesting I was faced with it when migrating to v8 (note v9 also exposes issue) from v0.30 with which there's no such problem.

This bug prevents constructing efficient flows which may intentionally introduce safe race conditions, e.g. I've needed to refactor part of a flow from parallel to consecutive due to that issue: https://github.com/serverless/serverless/commit/548bd986e4dafcae207ae80c3a8c3f956fbce037

Was this page helpful?
0 / 5 - 0 ratings