diff --git a/lib/internal/fs/rimraf.js b/lib/internal/fs/rimraf.js index 675c2448c4568c5..d6ce831884516ce 100644 --- a/lib/internal/fs/rimraf.js +++ b/lib/internal/fs/rimraf.js @@ -219,6 +219,12 @@ function _unlinkSync(path, options) { i < tries && options.retryDelay > 0) { sleep(i * options.retryDelay); + } else { + // The file is already gone. + if (err.code === 'ENOENT') { + return; + } + throw err; } } } @@ -259,10 +265,18 @@ function _rmdirSync(path, options, originalErr) { i < tries && options.retryDelay > 0) { sleep(i * options.retryDelay); + } else { + // The file is already gone. + if (err.code === 'ENOENT') { + return; + } + throw err; } } } } + + throw originalErr; } } diff --git a/test/parallel/test-fs-rm.js b/test/parallel/test-fs-rm.js index 5bb5d2de553eee0..aea3511e7d87c9a 100644 --- a/test/parallel/test-fs-rm.js +++ b/test/parallel/test-fs-rm.js @@ -280,3 +280,24 @@ function removeAsync(dir) { message: /^The value of "options\.maxRetries" is out of range\./ }); } + +{ + // Check that deleting a file that cannot be accessed using rmsync throws + const dirname = nextDirPath(); + try { + fs.mkdirSync(dirname, { recursive: true }); + fs.writeFileSync(path.join(dirname, 'text.txt'), 'hello'); + fs.chmodSync(dirname, '500'); + assert.throws(() => { + fs.rmSync(`${dirname}/text.txt`, { force: true }); + }, { + code: 'EACCES', + syscall: 'unlink', + name: 'Error', + errno: -13, + }); + } finally { + fs.chmodSync(dirname, '777'); + fs.rmSync(`${dirname}/text.txt`, { force: true }); + } +}