Node.js
fs.createWriteStream
ENOENT error
file system
error handling

Why is fs.createWriteStream throwing a Error ENOENT no such file or directory error?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

ENOENT from fs.createWriteStream() means Node.js could not open the path you gave it because some part of that path does not exist. The most important thing to understand is that createWriteStream() can create a file, but it cannot create missing parent directories for you.

What ENOENT Usually Means Here

A write stream like this is valid when the directory already exists:

javascript
const fs = require("fs");

const stream = fs.createWriteStream("./output/report.txt");

If ./output does not exist, Node throws an error similar to:

text
Error: ENOENT: no such file or directory, open './output/report.txt'

So the error is rarely about the file name itself. It is usually about one of these:

  • the parent directory does not exist
  • the path is relative to a different working directory than you expected
  • a path segment is misspelled
  • you built the path incorrectly on the current OS

createWriteStream() Creates Files, Not Folder Trees

This distinction is the root of most confusion.

javascript
const fs = require("fs");

fs.createWriteStream("./logs/app.log");

If ./logs exists, Node can create app.log.

If ./logs does not exist, you get ENOENT.

The fix is to create the directory first:

javascript
1const fs = require("fs");
2const path = require("path");
3
4const outputDir = path.join(__dirname, "logs");
5fs.mkdirSync(outputDir, { recursive: true });
6
7const stream = fs.createWriteStream(path.join(outputDir, "app.log"));
8stream.write("started\n");
9stream.end();

Relative Paths Are Resolved from process.cwd()

Another common mistake is assuming relative paths are resolved from the file containing the code. In Node.js, relative filesystem paths are resolved from the current working directory, not automatically from __dirname.

This can break when you run the same script from a different folder.

javascript
1const fs = require("fs");
2
3console.log("cwd:", process.cwd());
4console.log("__dirname:", __dirname);
5
6fs.createWriteStream("./output/report.txt");

If you want a path relative to the script file, build it explicitly:

javascript
const path = require("path");
const filePath = path.join(__dirname, "output", "report.txt");

That usually makes the code more predictable.

Always Listen for Stream Errors

Even when you think the path is correct, treat the stream as asynchronous and attach an error handler.

javascript
1const fs = require("fs");
2const path = require("path");
3
4const filePath = path.join(__dirname, "output", "report.txt");
5fs.mkdirSync(path.dirname(filePath), { recursive: true });
6
7const stream = fs.createWriteStream(filePath);
8
9stream.on("error", err => {
10  console.error("write failed:", err.message);
11});
12
13stream.write("hello\n");
14stream.end();

That gives you a clean place to diagnose production issues instead of crashing mysteriously.

Cross-Platform Path Handling

Hardcoded path strings can also cause trouble, especially if you mix separators or make assumptions about Windows drive letters.

Prefer path.join() or path.resolve():

javascript
1const path = require("path");
2
3const filePath = path.resolve("data", "exports", "daily.csv");
4console.log(filePath);

This avoids a lot of subtle path bugs and keeps the code portable.

ENOENT Versus Permission Errors

Do not confuse ENOENT with permission failures such as EACCES or EPERM.

  • 'ENOENT means the path could not be found'
  • 'EACCES or EPERM usually mean the path exists but cannot be accessed the way you requested'

That distinction saves time during debugging.

Common Pitfalls

The biggest pitfall is assuming createWriteStream() will create missing folders automatically. It will not.

Another pitfall is using a relative path without checking process.cwd(). Code that works in one launch context can fail in another for that reason alone.

A third pitfall is forgetting to create nested parent directories when writing into deep paths such as reports/2026/03/summary.txt.

Finally, do not ignore the stream's error event. Filesystem issues are runtime conditions, not just coding mistakes.

Summary

  • 'ENOENT from fs.createWriteStream() usually means some part of the path does not exist'
  • The method can create a file, but not missing parent directories
  • Create the parent directory first, using recursive directory creation if needed, before opening the stream
  • Prefer __dirname plus path.join() when you want paths relative to the current script
  • Attach an error handler so path problems are easier to diagnose

Course illustration
Course illustration

All Rights Reserved.