node icon indicating copy to clipboard operation
node copied to clipboard

[fs.rm] Reports `ENOTEMPTY` randomly

Open SukkaW opened this issue 1 year ago • 3 comments

Version

v22.5.1

Platform

Darwin Sukka-Macbook-Pro.local 24.0.0 Darwin Kernel Version 24.0.0: Mon Aug 12 21:27:51 PDT 2024; root:xnu-11215.1.10~5/RELEASE_ARM64_T6020 arm64

Subsystem

No response

What steps will reproduce the bug?

I was building a rollup plugin that deletes the output folder/files:

import type { Plugin as RollupPlugin } from 'rollup';
import fsp from 'node:fs/promises';

export function cleandir(): RollupPlugin {
  return {
    name: 'cleandir',
    renderStart: {
      order: 'pre',
      async handler(outputOptions) {
        if (outputOptions.dir) {
          await fsp.rm(outputOptions.dir, { recursive: true, force: true });
          await fsp.mkdir(outputOptions.dir, { recursive: true });
        }
        if (outputOptions.file) {
          await fsp.rm(outputOptions.file, { recursive: true, force: true });
        }
      }
    }
  };
}

But I randomly encounter the following error:

src/index.ts → dist, dist...
[!] (plugin cleandir) Error: ENOTEMPTY: directory not empty, rmdir 'dist'
Error: ENOTEMPTY: directory not empty, rmdir 'dist'


ELIFECYCLE  Command failed with exit code 1.

How often does it reproduce? Is there a required condition?

About 1 in 8 times.

What is the expected behavior? Why is that the expected behavior?

fsp.rm should never reports ENOTEMPTY: directory not empty

What do you see instead?

Error: ENOTEMPTY: directory not empty, rmdir 'dist'

Additional information

I am running a parallel build inside a relatively large monorepo, which might have many file descriptors opened at once.

SukkaW avatar Aug 25 '24 23:08 SukkaW

Hi! Can you make a reproduction without rollup as a dependency? Preferably, without any non-built in dependencies?

Secondly, can you try reproducing in v22.7.0? (Or v22.8.0 depending on when you see this message)

avivkeller avatar Aug 25 '24 23:08 avivkeller

Hi! Can you make a reproduction without rollup as a dependency? Preferably, without any non-built in dependencies?

Since it happens randomly, I guess it might have something to do with many existing opened fs descriptors.

I am trying to extract a minimum reproduction.

SukkaW avatar Aug 25 '24 23:08 SukkaW

I am trying to extract a minimum reproduction.

Great! Until that is done, it'll be hard to people to see what is going wrong.

avivkeller avatar Aug 27 '24 17:08 avivkeller

This issue/PR was marked as stalled, it will be automatically closed in 30 days. If it should remain open, please leave a comment explaining why it should remain open.

github-actions[bot] avatar Sep 14 '24 22:09 github-actions[bot]

This is not a bug, sometimes OS are like that?

If an EBUSY, EMFILE, ENFILE, ENOTEMPTY, or EPERM error is encountered, Node.js will retry the operation with a linear backoff wait of retryDelay milliseconds longer on each try. This option represents the number of retries. This option is ignored if the recursive option is not true. Default: 0.

Please use something like await fsp.rm(outputOptions.dir, { recursive: true, force: true, maxRetries: ANY });

Ref: https://nodejs.org/docs/latest-v22.x/api/fs.html#fspromisesrmpath-options

juanarbol avatar Oct 31 '24 06:10 juanarbol

Closing this, as this is an expected and documented behaviour.

juanarbol avatar Oct 31 '24 06:10 juanarbol