How to fix Error: ENOTDIR: not a directory, scandir '/path/to/file.txt' in Node.js

Node.jsBEGINNERMEDIUMUpdated Dec 9, 2025ยท 204 views

This error occurs when Node.js file system operations expect a directory path but receive a file path instead. It commonly appears with fs.readdir(), fs.scandir(), or file watching utilities.

Quick fix

Fixes ENOTDIR

Error: ENOTDIR: not a directory, scandir '/path/to/file.txt'
  1. Identify the problematic path
  2. Verify the path type before reading
  3. Fix recursive directory operations
  4. Update file watching configurations
node.js โ€” error
Error: ENOTDIR: not a directory, scandir '/path/to/file.txt'
Error: ENOTDIR: not a directory, scandir '/path/to/file.txt'

What this error means

The ENOTDIR (Error: NOT a DIRectory) error is a system-level error that occurs when a Node.js operation expects a directory but encounters a regular file instead. This typically happens with directory-reading operations like fs.readdir(), fs.readdirSync(), or fs.scandir() when they're passed a file path instead of a directory path. The error originates from the underlying operating system when attempting to list directory contents of something that isn't actually a directory. This is a protective mechanism that prevents incorrect file system operations. This error is particularly common in recursive file operations, file watching utilities (like Webpack's Watchpack, Nuxt, or the watch npm package), and dynamic command loaders where code automatically scans directories but mistakenly tries to process individual files as directories.

Typical symptoms

  • Application crashes with "ENOTDIR: not a directory, scandir" message
  • File watching tools fail during initial scan or hot reload
  • Build tools like Webpack or Vite throw errors during compilation
  • Dynamic module loaders fail when reading command directories
  • Recursive directory operations stop unexpectedly
  • Error message includes a file path (ending in .js, .json, .txt, etc.) instead of a directory

Common causes

  1. Passing a file path to fs.readdir(), fs.readdirSync(), or similar directory-reading functions
  2. Recursive directory traversal that attempts to read files as if they were directories
  3. File watching configuration pointing to individual files instead of directories
  4. Incorrect path construction that references a file when a directory was intended
  5. Symlinks or shortcuts pointing to files when directories are expected
  6. Path variables containing file paths mixed with directory paths in iteration loops
  7. Incorrect glob patterns or path filters that include files in directory operations

How to fix "Error: ENOTDIR: not a directory, scandir '/path/to/file.txt'"

1Identify the problematic path

Examine the error message to identify which path is causing the issue. The error will show the exact path that was treated as a directory:

bash
Error: ENOTDIR: not a directory, scandir '/path/to/file.txt'

The path in the error message (e.g., file.txt) is a file, not a directory. Note the file extension or check if it's a known file in your project.

2Verify the path type before reading

Add a check to ensure the path is a directory before attempting to read it. Use fs.statSync() or fs.lstatSync() to verify:

javascript
const fs = require('fs');
const path = require('path');

function readDirectorySafely(dirPath) {
  try {
    const stats = fs.statSync(dirPath);

    if (!stats.isDirectory()) {
      console.log(`Skipping file: ${dirPath}`);
      return [];
    }

    return fs.readdirSync(dirPath);
  } catch (error) {
    console.error(`Error reading ${dirPath}:`, error.message);
    return [];
  }
}

// Usage
const items = readDirectorySafely('/path/to/check');

This approach safely handles both files and directories.

3Fix recursive directory operations

If you're recursively traversing directories, ensure you only call directory operations on actual directories:

javascript
const fs = require('fs');
const path = require('path');

function traverseDirectory(dirPath) {
  const items = fs.readdirSync(dirPath);

  items.forEach(item => {
    const fullPath = path.join(dirPath, item);
    const stats = fs.statSync(fullPath);

    if (stats.isDirectory()) {
      // Recurse into subdirectories
      traverseDirectory(fullPath);
    } else if (stats.isFile()) {
      // Process files
      console.log('Processing file:', fullPath);
    }
  });
}

traverseDirectory('./my-directory');

Always check stats.isDirectory() before making recursive calls.

4Update file watching configurations

If the error occurs with file watchers (Webpack, Vite, etc.), ensure your configuration points to directories, not files:

webpack.config.js:

javascript
module.exports = {
  // Watch the directories, not individual files
  watchOptions: {
    ignored: /node_modules/,
    // Don't watch individual files
  },
  // Ensure entry points and context are correct
  context: path.resolve(__dirname, 'src'),
};

For watch libraries:

javascript
const watch = require('watch');

// Watch a directory, not a file
watch.watchTree('./src', (f, curr, prev) => {
  if (typeof f === "object" && prev === null && curr === null) {
    // Finished walking the tree
  } else {
    console.log('File changed:', f);
  }
});
5Fix dynamic module loading paths

If you're dynamically loading commands or modules, ensure you're reading the directory, not including files in the path:

Incorrect (causes ENOTDIR):

javascript
const commandFiles = fs.readdirSync('./commands/ping.js'); // File path!

Correct:

javascript
const path = require('path');
const fs = require('fs');

const commandsDir = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsDir)
  .filter(file => file.endsWith('.js'));

commandFiles.forEach(file => {
  const filePath = path.join(commandsDir, file);
  const command = require(filePath);
  console.log('Loaded command:', command);
});

Always use the directory path for readdirSync(), then join individual file names.

Advanced notes

Symbolic Links and Hard Links:
When dealing with symbolic links, use fs.lstatSync() instead of fs.statSync() if you want to check the link itself rather than the target. This can prevent ENOTDIR errors when symlinks point to files but are treated as directories.

Platform Differences:
On Windows, there's a historical inconsistency where fs.readdir() might not always report ENOTDIR errors correctly for certain edge cases. This has been fixed in modern Node.js versions, but if you're supporting older environments, add explicit isDirectory() checks.

Performance Considerations:
When scanning large directory trees, calling statSync() on every entry can impact performance. Consider using fs.readdir() with the withFileTypes option (Node.js 10.10+):

javascript
const entries = fs.readdirSync(dirPath, { withFileTypes: true });

entries.forEach(entry => {
  if (entry.isDirectory()) {
    // Process directory without additional stat call
    const subDir = path.join(dirPath, entry.name);
    processDirectory(subDir);
  }
});

This avoids the overhead of separate statSync() calls for each entry.

TypeScript Type Guards:
When working with TypeScript, create type guards for directory operations:

typescript
import { Stats } from 'fs';

function isDirectory(stats: Stats): boolean {
  return stats.isDirectory();
}

function safeReadDir(dirPath: string): string[] {
  const stats = fs.statSync(dirPath);
  if (!isDirectory(stats)) {
    throw new TypeError(`Path is not a directory: ${dirPath}`);
  }
  return fs.readdirSync(dirPath);
}

Frequently asked questions

What does "ENOTDIR" mean?
js operation expects a directory but encounters a regular file instead. scandir() when they're passed a file path instead of a directory path. The error originates from the underlying operating system when attempting to list directory contents of something that isn't actually a directory.
How do I fix "ENOTDIR"?
This error occurs when Node.js file system operations expect a directory path but receive a file path instead. It commonly appears with fs.readdir(), fs.scandir(), or file watching utilities.
What causes "ENOTDIR"?
Passing a file path to fs.readdir(), fs.readdirSync(), or similar directory-reading functions Recursive directory traversal that attempts to read files as if they were directories File watching configuration pointing to individual files instead of directories
Is the "ENOTDIR" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading