denoland/deno · error · Error

ERR_CHILD_PROCESS_IPC_REQUIRED

ERR_CHILD_PROCESS_IPC_REQUIRED

Error message

Forked processes must have an IPC channel, missing value 'ipc' in options.stdio

What it means

fork() sets up an IPC channel so parent and child can exchange messages (process.on('message'), child.send()). When options.stdio is a string, fork appends 'ipc' automatically; when it is an array, the array must contain 'ipc' itself, otherwise ERR_CHILD_PROCESS_IPC_REQUIRED is thrown.

Source

Thrown at ext/node/polyfills/child_process.ts:285

    if (result.traceEventCategories) {
      options.env = {
        ...(options.env ?? lazyProcess().default.env),
        DENO_NODE_TRACE_EVENT_CATEGORIES: result.traceEventCategories,
      };
    }
  }

  if (typeof options.stdio === "string") {
    options.stdio = stdioStringToArray(options.stdio, "ipc");
  } else if (!ArrayIsArray(options.stdio)) {
    // Use a separate fd=3 for the IPC channel. Inherit stdin, stdout,
    // and stderr from the parent if silent isn't set.
    options.stdio = stdioStringToArray(
      options.silent ? "pipe" : "inherit",
      "ipc",
    );
  } else if (!ArrayPrototypeIncludes(options.stdio, "ipc")) {
    throw new ERR_CHILD_PROCESS_IPC_REQUIRED("options.stdio");
  }

  options.execPath = options.execPath || Deno.execPath();
  options.shell = false;

  // deno-lint-ignore no-explicit-any
  (options as any)[kNeedsNpmProcessState] = true;

  return spawn(options.execPath, args, options);
}

function spawn(
  command: string,
  argsOrOptions?: string[] | SpawnOptions,
  maybeOptions?: SpawnOptions,
): ChildProcess {
  const args = ArrayIsArray(argsOrOptions) ? argsOrOptions : [];
  let options = !ArrayIsArray(argsOrOptions) && argsOrOptions != null

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Append 'ipc' as the fourth stdio entry: { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] }
  2. Use the string shorthand { stdio: 'pipe' } which auto-adds the IPC channel
  3. If no messaging between processes is needed, use spawn() instead of fork()

Example fix

// before
fork('child.js', [], { stdio: ['pipe', 'pipe', 'pipe'] });
// after
fork('child.js', [], { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] });
Defensive patterns

Strategy: validation

Validate before calling

if (Array.isArray(options.stdio) && !options.stdio.includes('ipc')) {
  options.stdio = [...options.stdio, 'ipc'];
}
fork(modulePath, [], options);

Type guard

const stdioHasIpc = (stdio) => typeof stdio === 'string' || (Array.isArray(stdio) && stdio.includes('ipc'));

Prevention

When it happens

Trigger: fork('child.js', [], { stdio: ['pipe', 'pipe', 'pipe'] }); fork(modulePath, { stdio: ['ignore', 'inherit', 'inherit'] }); any fork with a custom stdio array lacking 'ipc'.

Common situations: Copying a spawn stdio configuration into fork; trying to silence child output with an explicit array and unintentionally dropping the IPC entry.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/8f3576dca41fa49e. Report an issue: GitHub.