Use a buffered child-process API for a result with a known size bound. For ongoing output, use spawn and consume both output streams incrementally. Raising maxBuffer delays failure when the producer never finishes.
Reproduce the boundary in a disposable fixture
Choose buffered completion or incremental consumption for child-process output.
Use a new empty temporary directory for this fixture. The example creates only local test data. Commands marked with example.invalid do not identify a real service.
const assert = require('node:assert/strict');
const {execFile, spawn} = require('node:child_process');
execFile(process.execPath, ['-e', "process.stdout.write('x'.repeat(4096))"],
{maxBuffer: 1024}, (error) => {
assert(error);
console.log(error.code);
const child = spawn(process.execPath,
['-e', "process.stdout.write('x'.repeat(4096))"]);
let bytes = 0;
child.stdout.on('data', chunk => { bytes += chunk.length; });
child.stderr.on('data', chunk => process.stderr.write(chunk));
child.on('error', err => { throw err; });
child.on('close', code => {
assert.equal(code, 0);
assert.equal(bytes, 4096);
console.log({bytes});
});
});Observed result
ERR_CHILD_PROCESS_STDIO_MAXBUFFER
{ bytes: 4096 }What the result means
The first child emits a deliberately small but oversized result for the configured limit. The callback reports an error. The second sends the same bytes through a stream, and the parent counts them without retaining the entire output. Counting bytes makes this fixture independent of line breaks and character decoding. execFile is used to avoid a shell; the buffering decision applies separately from whether the command uses a shell.
Choose the correction for your workflow
For a finite command, estimate an explicit upper bound, allow for stderr as well as stdout and handle the error without parsing a truncated result as complete. For a monitor or exporter, consume output as it arrives and define who stops the child. A streaming API is only helpful if the consumer also stays bounded: appending every chunk to an array recreates the memory problem. If you parse lines, retain only the incomplete final line and bound its length. A child that requires a terminal may need different flags or a terminal-aware interface.
Limits and the next check
The fixture uses Node v26.5.0 and a finite synthetic child, not an interactive system monitor. Real commands can buffer internally and can emit multibyte text across chunks. maxBuffer is a byte limit, not a count of visible characters. Add timeout, cancellation and backpressure policies for the real producer; do not introduce a shell merely to fix buffering.
Related: Compare the related workflow boundary.
This isolated example was executed on macOS on November 10, 2026 (KST). Available tools: node v26.5.0, git git version 2.39.3 (Apple Git-145), npm 11.17.0, jq jq-1.7.1-apple. Shell fixtures use Bash and repository-path identity uses Python 3. This checks the illustrated contract, not your project, host service or every tool version.