Discrepancy between `fs.rmSync` and `fs/promises.rm` behavior with `.` and `..` in paths
还没有人认领这个 Issue。
- 主要语言
- JavaScript
- 星标
- 122k
- 派生
- 37.4k
- 平均合并
- 4 天 3 小时
- 30 天内合并 PR
- 272
描述
Version
v25.6.1
Platform
Darwin moxy.lan 25.3.0 Darwin Kernel Version 25.3.0: Wed Jan 28 20:47:03 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6031 arm64
Subsystem
lib/internal/fs/rimraf.js
What steps will reproduce the bug?
Create a nested folder:
mkdir -p a/b/c/d
Attempt to delete with this weirdly constructed path:
Welcome to Node.js v25.6.1.
Type ".help" for more information.
> await require('fs/promises').rm('a/b/../.', { recursive: true, force: true })
Uncaught [Error: EINVAL: invalid argument, rmdir 'a/b/../.'] {
errno: -22,
code: 'EINVAL',
syscall: 'rmdir',
path: 'a/b/../.'
}
Verify that nothing was removed:
$ tree
./
└── a/
└── b/
└── c/
└── d/
Attempt to delete synchronously:
> require('fs').rmSync('a/b/../.', { recursive: true, force: true })
undefined
It was (mostly?) removed:
$ tree
./
└── a/
The weird thing is that a/b/../. should resolve to just a, so it's weird that it only deletes up to b. It's almost as if the rmSync method is coalescing /../. into just /.
Also, if the . is not the last item, then it seems to be fine? a/b/.././b deletes the b folder, and a/b/.. deletes just b, but not a.
At least, it seems like the sync and asynchronous methods should either both fail, or both succeed, with the same error.
How often does it reproduce? Is there a required condition?
every time, see repro steps above
What is the expected behavior? Why is that the expected behavior?
sync and asynchronous rm methods should fail and succeed in the same way on the same input.
What do you see instead?
Some cases where rmSync succeeds, and fs/promises.rm fails.
Additional information
I have a fix that I could land in the upstream rimraf library, and I'd of course be happy to send a PR to node to bring it back into alignment, since there have also been some improvements in performance and Windows reliability.
But it'd be good to know what the intended behavior is, so that the errors can be made consistent with Node's intended design first.
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从 lib/internal/fs/rimraf.js 开始,分别对 fs/promises.rm 和 fs.rmSync 运行已报告的 a/b/../. 复现。比较每个路径的处理方式,并在检查周围的文件系统测试之前确定预期的一致行为。完成标准是:对于这些点路径情况,两个 API 的行为一致,并且回归测试覆盖能够保护该行为。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- javascript, nodejs
- 领域
- backend, operating-systems
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 活跃
- 描述清晰度
- 基本清楚
- 新手友好度
- 55/100