Node.jsでの「Error: EISDIR: illegal operation on a directory, read」の解決方法

初級💚 Node.js2026-04-27| Node.js(全バージョン)。fsモジュールやGulp、Webpack、Viteなどのビルドツールを使用している際に、Windows、macOS、Linux環境で発生します。

Error Message

Error: EISDIR: illegal operation on a directory, read
#nodejs#fs#javascript#backend

背景フォルダの処理中やビルドスクリプトの実行中に、プロセスが突然停止したのではないでしょうか。ターミナルには「Error: EISDIR: illegal operation on a directory, read」というメッセージが表示されます。これは、コードがディレクトリを開いて、それを単一のファイルであるかのように内容を読み取ろうとしているために発生します。

このエラーは、開発者がサブディレクトリを含むフォルダをループ処理している場合や、設定変数が /uploads/image.png ではなく /uploads/ を指している場合によく見られます。Node.jsはファイルを期待していますが、代わりにフォルダが見つかったのです。

なぜこれが発生するのかEISDIRは「Error, Is Directory(エラー、ディレクトリです)」の略です。システムレベルでは、ディレクトリの読み取りにはファイルとは異なる権限とメソッドが必要です。fs.readFile()fs.createReadStream() などの関数は、ファイルディスクリプタを期待しています。フォルダへのパスを渡すと、オペレーティングシステムはそのリクエストを拒否します。.txt.json ファイルを読むのと同じ方法で、フォルダの生のバイナリデータを読み取ることはできません。

デバッグプロセス最初のステップは、クラッシュを引き起こしている正確なパスを特定することです。スタックトレースが曖昧な場合は、失敗している操作の直前にログを追加して、変数の実際の内容を確認してください。

const filePath = path.join(__dirname, 'data', fileName);
console.log('パスを読み取ろうとしています:', filePath);
const data = fs.readFileSync(filePath);

出力を注意深く確認してください。fileName が未定義(undefined)であったり、パスがフォルダ名で唐突に終わっていたりすることに気づくかもしれません。Webpack や Vite などのツールでエラーが発生している場合は、エントリポイントを確認してください。よくある間違いは、ソースマップやアセットのインクルード先を特定のファイルではなくディレクトリに指定してしまうことです。

解決策1:より適切なフィルタリングのために withFileTypes を使用する多くのアイテムがあるディレクトリをループ処理する場合、すべてのアイテムがファイルであると決めつけないでください。モダンな Node.js でこれを処理する最も効率的な方法は、fs.readdirSyncwithFileTypes オプションを使用することです。これにより、アイテムごとに余計なシステムコールを行うことなく、ファイルタイプを確認できます。

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

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

entries.forEach(entry => {
    const fullPath = path.join(dirPath, entry.name);
    
    if (entry.isDirectory()) {
        console.log(`ディレクトリをスキップ中: ${entry.name}`);
        return;
    }

    const content = fs.readFileSync(fullPath, 'utf8');
    console.log(`正常に読み取りました: ${entry.name}`);
});

解決策2:Globパターンを洗練させるGulp や同様のビルドツールでこのエラーが発生する場合、glob パターンが広すぎる可能性があります。例えば、gulp.src('src/assets/*') は、サブフォルダを含むそのフォルダ内のすべてを取得するようにツールに指示します。その後、Gulp はそれらのサブフォルダをファイルとして読み込もうとし、EISDIR クラッシュにつながります。

これを修正するには、ファイル拡張子を具体的に指定します:

// 問題あり:フォルダを取得してしまう
gulp.src('src/assets/*')

// 安全:特定のファイルタイプのみを取得する
gulp.src('src/assets/**/*.{png,jpg,svg}')

解決策3:Multerのパス問題を修正するExpress.js アプリケーションでは、ファイルのアップロードを処理する際にこのエラーがよく発生します。Multer は主に2つのプロパティを提供します:destination(フォルダ)と path(特定のファイル)です。もし destination を読み取ろうとすると、アプリはクラッシュします。

// これは EISDIR を引き起こします
fs.readFile(req.file.destination, (err, data) => { ... });

// こちらが正しい方法です
fs.readFile(req.file.path, (err, data) => { ... });

検証特定のパスが原因であることを確認したいですか? ターミナルで次のワンライナーを実行してみてください:

node -e "require('fs').readFileSync('./your-suspect-path')"

もし EISDIR エラーが返ってきたら、そのパスがディレクトリであることが確認できたことになります。フィルタを適用したりパス文字列を修正したりすれば、コマンドはファイルのバッファを返すか、コードがそれを完全にスキップするようになるはずです。

ベストプラクティスのまとめ- フォルダの内容を決めつけない: ディレクトリをループ処理する際は、常に .isFile() をチェックするか withFileTypes を使用してください。- 入力をサニタイズする: パスがユーザーや設定ファイルからのものである場合は、読み取り関数を呼び出す前にそれがディレクトリでないことを確認してください。- path モジュールを使用する: 手動での文字列結合は避けてください。Node.js がパスをディレクトリと誤認する原因となる末尾のスラッシュを防ぐために、path.join() を使用してください。

Related Error Notes