denoland/deno · error · ERR_UNKNOWN_SIGNAL

ERR_UNKNOWN_SIGNAL

ERR_UNKNOWN_SIGNAL

Error message

Unknown signal: ${signal}

What it means

convertToValidSignal normalizes signal arguments in Deno's node compat layer: a numeric signal must exist in the signals-to-names mapping, a string must resolve (case-insensitively) through os.signals. Anything else throws ERR_UNKNOWN_SIGNAL. Its reachable call site is the killSignal option of child_process.spawn/SpawnSync (ext/node/polyfills/child_process.ts:348); an unknown name, typo, or unsupported-on-this-platform signal number is rejected before the process is spawned.

Source

Thrown at ext/node/polyfills/internal/util.mjs:182

    if (ObjectHasOwn(os.signals, key)) {
      signalsToNamesMapping[os.signals[key]] = key;
    }
  }

  return signalsToNamesMapping;
}

function convertToValidSignal(signal) {
  if (typeof signal === "number" && getSignalsToNamesMapping()[signal]) {
    return signal;
  }

  if (typeof signal === "string") {
    const signalName = os.signals[StringPrototypeToUpperCase(signal)];
    if (signalName) return signalName;
  }

  throw new ERR_UNKNOWN_SIGNAL(signal);
}

const codesWarned = new SafeSet();

const experimentalWarnings = new SafeSet();

function emitExperimentalWarning(feature, messagePrefix, code, ctor) {
  if (SetPrototypeHas(experimentalWarnings, feature)) return;
  SetPrototypeAdd(experimentalWarnings, feature);
  let msg =
    `${feature} is an experimental feature and might change at any time`;
  if (messagePrefix) {
    msg = messagePrefix + msg;
  }
  globalThis.process.emitWarning(msg, "ExperimentalWarning", code, ctor);
}

const pendingCodesWarned = new SafeSet();

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use standard names: killSignal: 'SIGTERM' or 'SIGKILL'
  2. Pull from the constants: killSignal: os.constants.signals.SIGTERM
  3. Validate config values against Object.keys(os.constants.signals) before spawning

Example fix

// before
spawn('sleep', ['5'], { killSignal: 'SIGKILLL' });

// after
spawn('sleep', ['5'], { killSignal: 'SIGKILL' });
Defensive patterns

Strategy: validation

Validate before calling

import * as os from 'node:os';

const KNOWN_SIGNALS = new Set(Object.keys(os.constants.signals));

function validKillSignal(sig: string): string {
  const s = sig.toUpperCase();
  if (KNOWN_SIGNALS.has(s)) return s;
  return 'SIGTERM';
}

spawn(cmd, args, { killSignal: validKillSignal(cfg.killSignal) });

Type guard

const isKnownSignal = (sig: string): boolean =>
  sig.toUpperCase() in os.constants.signals;

Try / catch

try {
  child = spawn(cmd, args, { killSignal: sig });
} catch (err) {
  if (err?.code === 'ERR_UNKNOWN_SIGNAL') child = spawn(cmd, args, { killSignal: 'SIGTERM' });
  else throw err;
}

Prevention

When it happens

Trigger: spawn(cmd, args, { killSignal: 'SIGKILL ' }) with trailing whitespace or 'SIG_STOP'-style typos; killSignal: 'SIGSTOPP'; a numeric signal constant copied from another OS (e.g. signals beyond the platform mapping); killSignal: undefined-typo keys like killSignal: signl.

Common situations: Cross-platform scripts assuming Linux signal names/numbers (SIGKILL=9) that differ on other platforms; typos in config-driven killSignal values; porting C signal numbers directly.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/a614e004915166fe. Report an issue: GitHub.