-
Notifications
You must be signed in to change notification settings - Fork 29.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inconsistent fs.rm behavior with "force" option on Windows vs mac/linux #45253
Comments
only tested this on a mac, but the behavior described above should be correct, as the path @VincentBailly are you sure you used the same paths on |
@dnalborczyk thank you for the response. The issue was not explicit enough, sorry. Let me clarify. The issue has to do with the option "force", the documentation says that the "force" option makes the function ignore exceptions when the path does not exist. https://nodejs.org/docs/latest-v16.x/api/fs.html#fspromisesrmpath-options |
On macOS: $ touch foo
$ rm -f foo/bar
rm: foo/bar: Not a directory
$ node -e 'fs.promises.rm("foo/bar", {force:true})'
node:internal/process/promises:289
triggerUncaughtException(err, true /* fromPromise */);
^
[Error: ENOTDIR: not a directory, stat 'foo/bar'] {
errno: -20,
code: 'ENOTDIR',
syscall: 'stat',
path: 'foo/bar'
}
Node.js v20.0.0-pre It looks like the built-in method also throw in this case. I suggest we update the documentation, I think we should try keeping the behavior consistent with the built-in tool. We should probably fix the Windows behavior then, I don't have a Windows machine to work on that, so if there are any volunteers that's be awesome. /cc @nodejs/fs |
Maybe this part requires rewording to avoid any ambiguity, but it sounds correct to me.
I'm not sure about direct native equivalent of $ touch foo
$ rm foo/bar
rm: cannot remove 'foo/bar': Not a directory
$ node -e 'require("fs").promises.rm("foo/bar")'
node:internal/process/promises:288
triggerUncaughtException(err, true /* fromPromise */);
^
[Error: ENOENT: no such file or directory, stat 'C:\foo\bar'] {
errno: -4058,
code: 'ENOENT',
syscall: 'stat',
path: 'C:\\foo\\bar'
}
$ rm -f foo/bar
[no error]
$ node -e 'require("fs").promises.rm("foo/bar", { force: true })'
[no error] So, behaviour with |
If this can help: on Linux (Ubuntu 22.04 & bash 5.0.17 & coreutils 8.30) the behavior is inconsistent between rm and nodejs $ rm -rf foo # cleanup to be sure
$ touch foo
$ rm foo/bar
rm: cannot remove 'foo/bar': Not a directory
$ rm -f foo/bar # no error
$ node -e 'require("fs").promises.rm("foo/bar")' # error expected, same as 'rm'
node:internal/process/promises:279
triggerUncaughtException(err, true /* fromPromise */);
^
[Error: ENOTDIR: not a directory, stat 'foo/bar'] {
errno: -20,
code: 'ENOTDIR',
syscall: 'stat',
path: 'foo/bar'
}
$ node -e 'require("fs").promises.rm("foo/bar", { force: true })' # error non expected, 'rm' command did not error out in same situation.
node:internal/process/promises:279
triggerUncaughtException(err, true /* fromPromise */);
^
[Error: ENOTDIR: not a directory, stat 'foo/bar'] {
errno: -20,
code: 'ENOTDIR',
syscall: 'stat',
path: 'foo/bar'
} |
Here is a summary of what different tools do in this scenario:
The NodeJS documentation says that rm is |
Since this is tightly related to the behavior of stat, let's also consider this:
|
It seems that fixing the |
On macOS: $ rm -rf foo
$ touch foo
$ stat foo/bar
stat: foo/bar: stat: Not a directory
$ node -e 'fs.statSync("foo/bar")'
node:internal/fs/utils:348
throw err;
^
Error: ENOTDIR: not a directory, stat 'foo/bar'
at Object.statSync (node:fs:1596:3)
at [eval]:1:4
at Script.runInThisContext (node:vm:129:12)
at Object.runInThisContext (node:vm:313:38)
at node:internal/process/execution:79:19
at [eval]-wrapper:6:22
at evalScript (node:internal/process/execution:78:60)
at node:internal/main/eval_string:28:3 {
errno: -20,
syscall: 'stat',
code: 'ENOTDIR',
path: 'foo/bar'
}
Node.js v18.11.0 |
Version
16.17.0
Platform
Linux my-VM 5.15.0-1022-azure #27~20.04.1-Ubuntu SMP Mon Oct 17 02:03:50 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Subsystem
node:fs
What steps will reproduce the bug?
touch foo node -e 'require("fs").promises.rm("foo/bar", { force: true })'
How often does it reproduce? Is there a required condition?
No condition, it reproduces on mac and on Linux.
What is the expected behavior?
Same behavior as on Windows, the function call succeeds and no exception is thrown.
What do you see instead?
Unhandled exception
Additional information
No response
The text was updated successfully, but these errors were encountered: