Node.jsエラーの修正: RangeError [ERR_CHILD_PROCESS_STDIO_MAXBUFFER]: stdout maxBuffer length exceeded

intermediate💚 Node.js2026-06-06| Node.js (全バージョン), Linux, macOS, Windows

Error Message

RangeError [ERR_CHILD_PROCESS_STDIO_MAXBUFFER]: stdout maxBuffer length exceeded
#nodejs#child_process#exec#spawn#debugging

エラーの内容

child_process.exec() を使用してシェルコマンドを実行している際、アプリケーションが突然次のような特定のエラーで停止することがあります:

RangeError [ERR_CHILD_PROCESS_STDIO_MAXBUFFER]: stdout maxBuffer length exceeded
    at Socket.ondata (node:internal/child_process:871:22)
    at Socket.emit (node:events:518:28)
    at addChunk (node:internal/streams/readable:559:12)
    at readableAddChunk (node:internal/streams/readable:532:9)
    at Socket.Readable.push (node:internal/streams/readable:373:10)
    at Pipe.onStreamRead (node:internal/stream_base_commons:190:23) {
  code: 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER'
}

原因

Node.jsは child_process.exec() を使用してコマンドを実行し、その終了を待ちます。このとき、コールバック関数に結果を渡す前に、すべての出力(stdout および stderr)を単一のメモリバッファに詰め込もうとします。デフォルトでは、Node.jsはこのバッファの上限を 1メガバイト (1,048,576 バイト) に制限しています。非常に古いバージョンのNode(v12未満)を使用している場合、その制限はわずか200キロバイトでした。

実行したコマンド(たとえば mysqldump、詳細な git log、あるいは巨大なディレクトリに対する find など)が1.1MBのテキストを生成すると、Node.jsはパニックを起こします。アプリが利用可能なすべてのRAMを使い果たしてサーバー全体をクラッシュさせるのを防ぐため、即座にプロセスを強制終了します。

解決策1:上限を引き上げる(クイックフィックス)

出力されるデータ量が正確に分かっており、それが巨大すぎない場合(例:1MBではなく5MBなど)、maxBuffer オプションを使用して手動で制限を増やすことができます。これがスクリプトを再び動作させるための最も速い方法です。

値はバイト単位で指定します。10MBの出力を許可するには、 1024 * 1024 * 10 を使用します。

const { exec } = require('child_process');

// バッファを10MBに増やす
const options = {
    maxBuffer: 1024 * 1024 * 10 
};

exec('cat logs/huge-access.log', options, (error, stdout, stderr) => {
    if (error) {
        console.error(`プロセスの実行に失敗しました: ${error.message}`);
        return;
    }
    console.log(`出力の ${stdout.length} 文字を読み込みました。`);
});

プロのヒント: これは、出力が予測可能で中規模な場合にのみ使用してください。出力が大幅に変動する場合、単にクラッシュするポイントを先送りにしているだけです。

解決策2:child_process.spawn を使用する(プロフェッショナルな修正)

大きなファイルや予測不能なデータを扱う場合、exec() は適切なツールではありません。代わりに child_process.spawn() に切り替えてください。

exec は映画を全編ダウンロードしてから視聴するようなもので、spawn はストリーミング視聴のようなものだと考えてください。 spawnstdoutstderrストリーム として提供します。データが到着するたびに小さなチャンク(通常64KB)で処理するため、ファイルサイズに関係なくメモリ使用量を低く抑えることができます。

const { spawn } = require('child_process');

// バッファリングする代わりにデータをストリーミングする
const child = spawn('cat', ['logs/huge-access.log']);

child.stdout.on('data', (chunk) => {
    console.log(`${chunk.length} バイトのチャンクを処理中...`);
    // ここでデータをパースするか、別のファイルにパイプする
});

child.stderr.on('data', (data) => {
    console.error(`エラー出力: ${data}`);
});

child.on('close', (code) => {
    console.log(`プロセスが終了コード ${code} で終了しました`);
});

いつ使用すべきか: 長時間実行されるタスク、データベースのエクスポート、あるいはS3バケットやHTTPレスポンスなどの別の送信先にデータを直接パイプする場合は、常に spawn を使用してください。

修正の検証方法

- **実際のサイズを確認する:** ターミナルでコマンドを実行し、`wc -c` にパイプして(例:`ls -R / | wc -c`)、扱う正確なバイト数を確認します。
- **選択した修正を適用する:** `maxBuffer` をその数値より少し大きく設定するか、`spawn` を使用してロジックを書き直します。
- **負荷テスト:** 予想される最大の入力値でスクリプトを実行します。`RangeError` が発生せずに完了すれば、問題ありません。

最終的な技術的考慮事項

- **UTF-16のコスト:** Node.jsでは、文字列はUTF-16エンコーディングを使用します。10MBの出力バッファは、実際には物理RAMの20MBを占有する可能性があります。`maxBuffer` を1GBに設定することは、`Out of Memory` (OOM) クラッシュを招くレシピとなります。
- **終了コード:** バッファがオーバーフローしなくても、プロセスが他の理由で失敗する可能性があることを忘れないでください。常に `exec` の `error` オブジェクトや、`spawn` の `close` イベントを確認してください。
- **Promise:** `async/await` を好む場合は、`util.promisify(exec)` を使用します。`maxBuffer` は第2引数として渡すことができます:`await execPromise('cmd', { maxBuffer: 1024 * 5000 })`。

Related Error Notes