fs.rm()

Removes a file or a directory, optionally deleting a whole tree and ignoring missing paths.

Signature
fs.rm(path[, options], callback)
  • Added in Node.js v14.14.0

Parameters

ParameterTypeDescription
$path<string> | <Buffer> | <URL>The file or directory to remove.
$optionsoptional<Object>= { force: false, recursive: false, maxRetries: 0, retryDelay: 100 }force <boolean> (default false) to ignore a missing path, recursive <boolean> (default false) to remove directory contents, maxRetries <integer> (default 0) for EBUSY/EMFILE/ENFILE/ENOTEMPTY/EPERM retries, and retryDelay <integer> (default 100) milliseconds of linear backoff between them. maxRetries and retryDelay are ignored unless recursive is true. A signal <AbortSignal> may also be given.
$callback<Function>Called as (err), null on success.

Return value

undefinedNothing. Success or failure is reported through the callback's err argument.

Errors

Reports ENOENT for a missing path unless force is true, ERR_FS_EISDIR when the path is a directory and recursive is false, and EACCES or EPERM on permission failures, all through the callback.

Changelog

  • PHP v17.3.0, v16.14.0path may be a WHATWG URL object using the file: protocol; previously such an object threw ERR_INVALID_ARG_TYPE.
  • PHP v14.14.0Added, replacing the recursive option of fs.rmdir() which was deprecated at the same time.

fs.rm() is Node's rm: it deletes a single file, or with recursive: true an entire directory tree. It replaced the deprecated recursive option on fs.rmdir() and is the function you should reach for today.

The two options do different jobs

People routinely pass both and assume they are one setting. recursive controls whether directory contents are removed — without it, a non-empty directory fails. force controls whether a missing path is an error — with it, deleting something that is not there succeeds silently, which makes cleanup code idempotent.

Retries are for Windows and network mounts

maxRetries and retryDelay exist because antivirus scanners and file indexers hold brief locks that surface as EBUSY or EPERM. They are ignored entirely unless recursive is true.

Handle with care

fs.rm(dir, { recursive: true, force: true }) is genuinely destructive and there is no trash can. Guard the path: a bug that leaves a variable as '' or '/' turns cleanup into data loss. Deletion is also not atomic — an error part-way through leaves a partially emptied tree behind.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Wipe a build or dist directory before regenerating it.
  • Tear down a temporary working directory in a test's afterEach hook.
  • Delete a cache folder from a CLI's clean command, without failing if it was never created.

Frequently asked questions

How do I delete a folder and everything in it in Node.js?

Call fs.rm(dir, { recursive: true, force: true }, callback), or the promise form await fs.promises.rm(dir, { recursive: true, force: true }). This replaced fs.rmdir() with recursive: true, which has been deprecated since Node 14.14.0.

What is the difference between fs.rm and fs.unlink?

fs.unlink() removes only files and fails on a directory; fs.rm() removes either, and with recursive: true removes a whole tree. Use unlink when the target is definitely a file, rm when it might be a directory.

Why does fs.rm still throw even though I passed force: true?

Because force only suppresses the missing-path error. A non-empty directory needs recursive: true, and permission failures (EACCES, EPERM) still surface regardless of either option.

More examples

What force actually suppresses

The first call reports ENOENT; the second reports null for the very same missing path. force affects only the missing-path case &mdash; it does not grant permission, and it does not let you delete a non-empty directory.

Example · javascript
const fs = require('node:fs');

fs.rm('never-existed', (err) => {
  console.log('without force:', err && err.code);

  fs.rm('never-existed', { force: true }, (err2) => {
    console.log('with force:', err2);
  });
});

What recursive actually enables

Removing a directory without recursive fails with ERR_FS_EISDIR, regardless of whether it is empty. Adding recursive deletes the tree and reports a null error, showing that force was never the missing ingredient here.

Example · javascript
const fs = require('node:fs');

fs.mkdirSync('cache/v1', { recursive: true });
fs.writeFileSync('cache/v1/blob', 'x');

fs.rm('cache', (err) => {
  console.log('directory without recursive:', err && err.code);

  fs.rm('cache', { recursive: true }, (err2) => {
    console.log('with recursive:', err2);
    console.log('gone:', !fs.existsSync('cache'));
  });
});

Removing a single file

With no options at all, fs.rm deletes a plain file exactly like fs.unlink(). Reach for rm when the target might be either a file or a directory, and unlink when you know it is a file.

Example · javascript
const fs = require('node:fs');

fs.writeFileSync('single.txt', 'one file');

fs.rm('single.txt', (err) => {
  if (err) throw err;
  console.log('file removed:', !fs.existsSync('single.txt'));
});

Discussion

  • Be the first to comment on this lesson.