This error occurs when a child process spawned by Node.js exits with a non-zero status code, indicating the command or script failed to execute successfully. Exit code 1 typically signals a general error condition in the child process.
This error is thrown by Node.js when using child process methods like `exec()`, `execSync()`, `spawn()`, or `execFile()` to run external commands or scripts. When the spawned process terminates with an exit code other than 0, Node.js interprets this as a failure and throws an error. Exit codes are a standard way for processes to communicate their termination status. By convention, exit code 0 means success, while any non-zero code indicates an error. Exit code 1 is the most generic error code, signaling that something went wrong but without specifying the exact nature of the failure. The error object contains valuable debugging information including the exit code (`error.code`), stdout, stderr, and the command that was executed. Understanding what the child process was trying to do and examining its output is key to resolving this issue.
First, modify your code to capture the full error information including stdout and stderr:
const { exec } = require('child_process');
exec('your-command', (error, stdout, stderr) => {
if (error) {
console.error('Error code:', error.code);
console.error('Signal:', error.signal);
console.error('stdout:', stdout);
console.error('stderr:', stderr);
console.error('Full error:', error);
return;
}
console.log('Success:', stdout);
});The stderr output often contains the actual error message from the failed command, which helps identify the root cause.
Run the exact command that's failing directly in your terminal to verify it works:
# Test the command manually
your-command arg1 arg2
# Check the exit code
echo $? # On Unix/Linux/macOS
echo %ERRORLEVEL% # On WindowsIf the command fails in the terminal with the same exit code, the issue is with the command itself, not Node.js. Fix the command first before retrying in your application.
If the child process generates significant output (logs, build artifacts, etc.), increase the buffer size:
const { exec } = require('child_process');
// Default maxBuffer is 1024 * 1024 (1MB)
exec('command-with-large-output', {
maxBuffer: 1024 * 1024 * 10 // 10MB
}, (error, stdout, stderr) => {
if (error) {
console.error('Error:', error);
return;
}
console.log(stdout);
});For very large output, consider using spawn() instead, which streams data rather than buffering it.
The spawn() method provides more granular control and better handling of output streams:
const { spawn } = require('child_process');
const child = spawn('command', ['arg1', 'arg2']);
child.stdout.on('data', (data) => {
console.log('stdout:', data.toString());
});
child.stderr.on('data', (data) => {
console.error('stderr:', data.toString());
});
child.on('exit', (code, signal) => {
if (code !== 0) {
console.error(`Process exited with code ${code}`);
}
});
child.on('error', (error) => {
console.error('Failed to start process:', error);
});This approach gives you real-time access to output and separates spawning errors from execution errors.
Ensure the child process has access to necessary environment variables and executables:
const { exec } = require('child_process');
exec('command', {
env: {
...process.env,
// Add or override specific variables
NODE_ENV: 'production',
PATH: `${process.env.PATH}:/additional/path`
},
cwd: '/path/to/working/directory'
}, (error, stdout, stderr) => {
// Handle result
});Missing environment variables or incorrect PATH settings are common causes of "command not found" errors that result in exit code 1.
Prevent indefinite hangs by adding a timeout:
const { exec } = require('child_process');
exec('long-running-command', {
timeout: 30000 // 30 seconds
}, (error, stdout, stderr) => {
if (error) {
if (error.killed) {
console.error('Process killed due to timeout');
} else {
console.error('Process failed:', error);
}
return;
}
console.log(stdout);
});After the timeout, Node.js sends a SIGTERM signal to the process, and if it doesn't exit, follows up with SIGKILL.
Exit Code Meanings: While exit code 1 is generic, many programs use specific codes: 2 for misuse of shell commands, 126 for permission denied, 127 for command not found, 128+n for signals (e.g., 130 for Ctrl+C). Check the documentation for the specific command you're executing.
Synchronous vs Asynchronous: The synchronous methods (execSync(), spawnSync()) throw exceptions directly while async methods use callbacks or events. Synchronous methods also block the event loop and should be avoided in production code except during initialization.
Shell Execution: exec() runs commands through a shell (/bin/sh on Unix, cmd.exe on Windows), which enables shell features like pipes and redirects but has security implications. Use execFile() or spawn() with shell: false when executing user-provided input to prevent command injection vulnerabilities.
Cross-Platform Considerations: Windows uses different command names (e.g., dir vs ls) and exit codes. Use packages like cross-spawn or execa for better cross-platform compatibility, or detect the platform with process.platform and adjust commands accordingly.
Debugging in CI/CD: In containerized environments or CI pipelines, child process failures often stem from missing system dependencies, different user permissions, or unavailable commands. Always test your commands in an environment that matches production as closely as possible.
Error: Listener already called (once event already fired)
EventEmitter listener already called with once()
Error: EACCES: permission denied, open '/root/file.txt'
EACCES: permission denied
Error: Invalid encoding specified (stream encoding not supported)
How to fix Invalid encoding error in Node.js readable streams
Error: EINVAL: invalid argument, open
EINVAL: invalid argument, open
TypeError: readableLength must be a positive integer (stream config)
TypeError: readableLength must be a positive integer in Node.js streams