The Error
While running a shell command via child_process.exec(), your application might suddenly die with this specific error:
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'
}
Why Does This Happen?
Node.js uses child_process.exec() to run a command and wait for it to finish. It tries to cram the entire output (stdout and stderr) into a single memory buffer before handing it back to your callback function. By default, Node.js caps this buffer at 1 Megabyte (1,048,576 bytes). If you're using an ancient version of Node (pre-v12), that limit was a tiny 200 Kilobytes.
When your command—perhaps a mysqldump, a verbose git log, or a find across a massive directory—generates 1.1 MB of text, Node.js panics. It kills the process immediately to prevent your app from eating all available RAM and crashing the entire server.
Solution 1: Raise the Ceiling (The Quick Fix)
If you know exactly how much data is coming and it isn't massive (e.g., 5MB instead of 1MB), you can manually increase the limit using the maxBuffer option. This is the fastest way to get your script running again.
The value is measured in bytes. To allow for 10MB of output, use 1024 * 1024 * 10.
const { exec } = require('child_process');
// Bump the buffer to 10MB
const options = {
maxBuffer: 1024 * 1024 * 10
};
exec('cat logs/huge-access.log', options, (error, stdout, stderr) => {
if (error) {
console.error(`Process failed: ${error.message}`);
return;
}
console.log(`Read ${stdout.length} characters of output.`);
});
Pro Tip: Only use this for predictable, medium-sized outputs. If the output varies wildly, you're just moving the crash point further down the road.
Solution 2: Use child_process.spawn (The Professional Fix)
For large files or unpredictable data, exec() is the wrong tool. Switch to child_process.spawn() instead.
Think of exec like downloading a whole movie before you start watching, while spawn is like streaming it. spawn provides stdout and stderr as Streams. You process data in small chunks (usually 64KB) as they arrive, keeping your memory footprint low regardless of the file size.
const { spawn } = require('child_process');
// Stream the data instead of buffering it
const child = spawn('cat', ['logs/huge-access.log']);
child.stdout.on('data', (chunk) => {
console.log(`Processing chunk of ${chunk.length} bytes...`);
// Parse your data here or pipe it to another file
});
child.stderr.on('data', (data) => {
console.error(`Error output: ${data}`);
});
child.on('close', (code) => {
console.log(`Process finished with exit code ${code}`);
});
When to use this: Always use spawn for long-running tasks, database exports, or when piping data directly to another destination like an S3 bucket or an HTTP response.
How to Verify the Fix
- **Check the real size:** Run your command in a terminal and pipe it to `wc -c` (e.g., `ls -R / | wc -c`) to see the exact byte count you're dealing with.
- **Apply your chosen fix:** Either bump `maxBuffer` slightly above that number or rewrite the logic with `spawn`.
- **Stress test:** Run the script with the largest expected input. If it completes without the `RangeError`, you're in the clear.
Final Technical Considerations
- **The UTF-16 Tax:** In Node.js, strings use UTF-16 encoding. A 10MB output buffer can actually occupy 20MB of physical RAM. Setting `maxBuffer` to 1GB is a recipe for an `Out of Memory` (OOM) crash.
- **Exit Codes:** Remember that even if the buffer doesn't overflow, the process can still fail for other reasons. Always check the `error` object in `exec` or the `close` event in `spawn`.
- **Promises:** If you prefer `async/await`, use `util.promisify(exec)`. You can pass the `maxBuffer` as the second argument: `await execPromise('cmd', { maxBuffer: 1024 * 5000 })`.

