This error occurs when you pass an invalid or unrecognized signal name to Node.js process.kill(). Common causes include using signal numbers instead of names, omitting the SIG prefix, or using platform-specific signals on unsupported systems.
This TypeError indicates that Node.js could not recognize the signal you passed to `process.kill()`. Unlike Unix system calls that accept numeric signal values, Node.js requires specific string signal names. The error typically appears as `TypeError [ERR_UNKNOWN_SIGNAL]: Unknown signal: <your-value>`, where the value you provided doesn't match any of the standard POSIX signal names that Node.js recognizes. Node.js validates signal names to ensure cross-platform compatibility and prevent errors from platform-specific signals being used where they're not supported.
Always use the complete signal name in uppercase with the 'SIG' prefix:
// ✅ CORRECT
process.kill(pid, 'SIGTERM');
process.kill(pid, 'SIGINT');
process.kill(pid, 'SIGKILL');
// ❌ WRONG - numeric values
process.kill(pid, 15); // TypeError
// ❌ WRONG - missing SIG prefix
process.kill(pid, 'TERM'); // TypeError
// ❌ WRONG - lowercase
process.kill(pid, 'sigterm'); // TypeErrorIf no signal is specified, Node.js defaults to 'SIGTERM'.
Verify that the signal you're using is supported on your target platform. Windows has limited signal support:
// Platform-safe signal handling
const signal = process.platform === 'win32' ? 'SIGTERM' : 'SIGUSR2';
try {
process.kill(pid, signal);
} catch (err) {
if (err.code === 'ERR_UNKNOWN_SIGNAL') {
console.error(`Signal ${signal} not supported on this platform`);
// Fallback to SIGTERM
process.kill(pid, 'SIGTERM');
}
}Universally supported signals:
- SIGTERM - Graceful termination (Windows: can listen, cannot send)
- SIGINT - Interrupt (Ctrl+C)
- SIGKILL - Force kill
- SIGQUIT - Quit with core dump
Unix/Linux only:
- SIGUSR1, SIGUSR2 - User-defined signals
- SIGHUP - Hangup signal
If you're accepting signal names from configuration or user input, validate them against Node.js's recognized signals:
const VALID_SIGNALS = [
'SIGABRT', 'SIGALRM', 'SIGBUS', 'SIGCHLD', 'SIGCONT', 'SIGFPE',
'SIGHUP', 'SIGILL', 'SIGINT', 'SIGIO', 'SIGIOT', 'SIGKILL',
'SIGPIPE', 'SIGPOLL', 'SIGPROF', 'SIGPWR', 'SIGQUIT', 'SIGSEGV',
'SIGSTKFLT', 'SIGSTOP', 'SIGSYS', 'SIGTERM', 'SIGTRAP', 'SIGTSTP',
'SIGTTIN', 'SIGTTOU', 'SIGUNUSED', 'SIGURG', 'SIGUSR1', 'SIGUSR2',
'SIGVTALRM', 'SIGWINCH', 'SIGXCPU', 'SIGXFSZ', 'SIGBREAK'
];
function killProcess(pid, signal = 'SIGTERM') {
if (!VALID_SIGNALS.includes(signal)) {
throw new Error(`Invalid signal: ${signal}`);
}
return process.kill(pid, signal);
}Alternatively, use os.constants.signals to check available signals:
import os from 'os';
function isValidSignal(signal) {
return signal in os.constants.signals;
}
if (isValidSignal('SIGTERM')) {
process.kill(pid, 'SIGTERM');
}For robust cross-platform process termination, implement a fallback strategy:
function terminateProcess(pid, graceful = true) {
const isWindows = process.platform === 'win32';
if (graceful) {
try {
// Try graceful shutdown first
if (isWindows) {
// Windows doesn't fully support SIGTERM
process.kill(pid, 'SIGINT');
} else {
process.kill(pid, 'SIGTERM');
}
// Give process time to clean up
return new Promise((resolve) => {
const timeout = setTimeout(() => {
// Force kill if not terminated
process.kill(pid, 'SIGKILL');
resolve();
}, 5000);
// Clear timeout if process exits
const interval = setInterval(() => {
try {
process.kill(pid, 0); // Check if process exists
} catch {
clearTimeout(timeout);
clearInterval(interval);
resolve();
}
}, 100);
});
} catch (err) {
if (err.code !== 'ESRCH') { // Process doesn't exist
throw err;
}
}
} else {
// Force kill
process.kill(pid, 'SIGKILL');
}
}Signal Zero for Process Existence Checking
You can pass signal 0 to process.kill() to check if a process exists without actually sending a signal. This is useful for process monitoring:
function isProcessRunning(pid) {
try {
process.kill(pid, 0);
return true;
} catch (err) {
return err.code === 'EPERM'; // Process exists but no permission
}
}Unsafe Signals
Some signals should never have listeners in Node.js because they leave the process in an unsafe state: SIGBUS, SIGFPE, SIGSEGV, and SIGILL. Attempting to handle these artificially can cause undefined behavior.
Signal Name Evolution
Prior to Node.js v12, signal numbers were sometimes accepted, but this was removed for consistency and cross-platform compatibility. Always use string signal names in modern Node.js applications.
Process Groups on Unix
On Unix systems, you can send signals to process groups using negative PIDs with process.kill(), but this doesn't work on Windows. Use platform-specific libraries like tree-kill for cross-platform process tree termination.
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