Create a directory if it does not exist in Node.js

Use recursive mkdir to create missing parents and accept an existing directory, while still handling permission and path conflicts.

Best practices
Illustration of files, modules, and dependencies

Call mkdir() with { recursive: true }. It creates missing parent directories and succeeds when the requested directory already exists. You do not need a separate existence check.

Choose an API style

For a short CommonJS script:

const fs = require('node:fs');
fs.mkdirSync('./output/logs', { recursive: true });

For an ES module using promises:

import { mkdir } from 'node:fs/promises';
await mkdir('./output/logs', { recursive: true });

Or use the callback API:

const fs = require('node:fs');
fs.mkdir('./output/logs', { recursive: true }, (error) => {
  if (error) {
    console.error('Could not create the directory:', error.message);
    return;
  }
  console.log('Directory is ready');
});

These examples resolve ./output/logs from the process's current working directory. Use an explicit base path if the directory should live beside a module or under a configured data directory. Asynchronous calls avoid blocking the JavaScript thread while waiting for filesystem work.

Avoid the check-then-create race

The recursive option was added in Node 10.12.0. Older examples often use existsSync() followed by mkdirSync(). Another process can create the directory between those calls, so the check is not a synchronization mechanism.

On supported releases, use recursive creation directly. Legacy environments need deliberate error handling or a compatible recursive implementation; checking first was never the only possible approach.

FAQ

Will an existing directory cause an error? Not in recursive mode merely because it already exists. That does not suppress permission errors, invalid path components, or a file occupying the requested location.

Why do I get EACCES? Inspect permissions on the target's parent path and the application's user. Use an intended writable location or correct a specific ownership problem instead of running the whole application with elevated privileges.

What does ENOTDIR mean? A component that must be a directory is a different kind of entry, for example data.txt/logs when data.txt is a file. A conflicting file at the final path may produce another error such as EEXIST, depending on the operation and platform.

Can it create several levels at once? Yes: mkdir('./a/b/c', { recursive: true }) creates missing ancestors. It is not a transaction: if a later step fails, already-created ancestors can remain.

Does it set permissions on an existing directory? Do not use mkdir as a permissions repair operation. Creation modes are also affected by the operating system and process umask; manage existing permissions explicitly when required.

References

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting