fs.writeFile()

Writes data to a file asynchronously, replacing the file if it already exists.

Signature
fs.writeFile(file, data[, options], callback)
  • Added in Node.js v0.1.29

Parameters

ParameterTypeDescription
$file<string> | <Buffer> | <URL> | <integer>Filename or file descriptor. When a file descriptor is used it is not closed automatically, and writing starts at the current position.
$data<string> | <Buffer> | <TypedArray> | <DataView>The contents to write. Objects are not coerced to strings; serialise them yourself with JSON.stringify() first.
$optionsoptional<Object> | <string>= { encoding: 'utf8', mode: 0o666, flag: 'w' }A string is treated as the encoding. As an object: encoding <string>|<null> (default 'utf8'), mode <integer> (default 0o666), flag <string> (default 'w'), flush <boolean> (default false) to fsync before closing, and signal <AbortSignal> to abort an in-progress write.
$callback<Function>Called as (err), where err is <Error> or <AggregateError> and is null on success.

Return value

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

Errors

Reports EACCES, ENOENT (missing parent directory), ENOSPC and EEXIST (with flag 'wx') through the callback; throws synchronously when data is an unsupported type such as a plain object, or when the callback is missing.

Changelog

  • PHP v21.0.0, v20.10.0The flush option is supported, running fs.fsync() after a successful write.
  • PHP v19.0.0Passing an object with its own toString function as data is no longer supported; it throws instead of being stringified.
  • PHP v16.0.0The error passed to the callback may be an AggregateError when more than one error occurs.
  • PHP v15.2.0, v14.17.0options may include an AbortSignal to abort an ongoing write.
  • PHP v14.0.0data no longer coerces unsupported input to strings; passing a plain object throws ERR_INVALID_ARG_TYPE.
  • PHP v10.0.0The callback parameter is no longer optional; omitting it throws a TypeError at runtime.

fs.writeFile() opens the path, writes data from the beginning, truncates whatever was there before, and closes the file. The default flag is 'w', so it creates the file if it is missing and destroys the previous contents if it is not. There is no “write only if changed” behaviour and no confirmation prompt.

What it will not do for you

  • It does not create parent directories. Writing to logs/today.txt when logs/ does not exist fails with ENOENT; call fs.mkdir() with recursive: true first.
  • It does not serialise objects. Since v14 a plain object throws ERR_INVALID_ARG_TYPE instead of writing [object Object] — pass a string, Buffer or TypedArray.
  • It is not atomic. A crash mid-write leaves a truncated file. For data you cannot afford to lose, write to a temporary name and fs.rename() over the target.

Concurrency and durability

Calling it twice on the same path without waiting for the first callback is unsafe: the two writes interleave and the result is undefined. Await one before starting the next. And a successful callback means the data reached the OS, not the physical disk — pass flush: true if you need it fsynced before you report success.

Example

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

When to use it

  • Persist an application's state or cache as JSON after a background job finishes.
  • Write a generated report, bundle or manifest to an output directory during a build.
  • Save an uploaded Buffer to disk once the request body has been fully received.

Frequently asked questions

Why does fs.writeFile fail with ENOENT when I am creating the file?

Because a directory in the path does not exist &mdash; fs.writeFile creates files, never folders. Call fs.mkdir(dir, { recursive: true }) before writing, or use path.dirname() to derive the directory to create.

How do I append to a file instead of overwriting it?

Use fs.appendFile(), or pass { flag: 'a' } to fs.writeFile(). The default flag is 'w', which truncates the file to zero length before writing.

Is fs.writeFile atomic?

No. A crash or a full disk part-way through leaves a truncated file, and two overlapping writes to the same path interleave unpredictably. For durability, write to a temporary file and fs.rename() it over the target, which is atomic on the same filesystem.

More examples

Writing JSON

The object has to be turned into a string first: passing `state` directly would throw ERR_INVALID_ARG_TYPE. The output is the pretty-printed JSON exactly as it landed on disk, indentation included.

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

const state = { runs: 3, lastStatus: 'ok' };

fs.writeFile('state.json', JSON.stringify(state, null, 2), 'utf8', (err) => {
  if (err) throw err;
  console.log(fs.readFileSync('state.json', 'utf8'));
  fs.unlinkSync('state.json');
});

Refuse to overwrite with flag 'wx'

The 'wx' flag means create-and-fail-if-it-exists. The first call succeeds, the second reports EEXIST, and the original contents survive untouched &mdash; a cheap way to claim a lock file or avoid clobbering someone else's output.

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

fs.writeFile('once.txt', 'created by the first writer\n', { flag: 'wx' }, (err) => {
  if (err) throw err;
  console.log('first write succeeded');

  fs.writeFile('once.txt', 'second writer\n', { flag: 'wx' }, (err2) => {
    console.log('second write error code:', err2 && err2.code);
    console.log('file still says:', fs.readFileSync('once.txt', 'utf8').trim());
    fs.unlinkSync('once.txt');
  });
});

Cancelling a write with an AbortSignal

An already-aborted signal makes the call fail immediately with an AbortError whose code is ABORT_ERR, and no file is created. Aborting a write that is already in flight does not roll it back, so a partially written file can remain in that case.

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

const controller = new AbortController();
controller.abort();

fs.writeFile('aborted.txt', 'never lands', { signal: controller.signal }, (err) => {
  console.log('error name:', err && err.name);
  console.log('error code:', err && err.code);
  console.log('file created:', fs.existsSync('aborted.txt'));
});

Discussion

  • Be the first to comment on this lesson.