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() starts a child process that talks to the parent over an IPC channel, so options.stdio must include 'ipc'. If stdio is an array without an 'ipc' entry, ERR_CHILD_PROCESS_IPC_REQUIRED is thrown. A stdio string such as 'pipe' is safe: stdioStringToArray() appends 'ipc' automatically.
Solutions
- Add 'ipc' to the stdio array: stdio: ['ignore', 'inherit', 'inherit', 'ipc'].
- Omit stdio entirely and let fork() configure it, or pass a stdio string.
- Use spawn() instead when you do not need channel messaging.
Example fix
// before
fork(workerPath, [], { stdio: ['ignore', 'pipe', 'pipe'] });
// after
fork(workerPath, [], { stdio: ['ignore', 'pipe', 'pipe', 'ipc'] }); Defensive patterns
Strategy: validation
Validate before calling
const stdio = Array.isArray(opts.stdio) ? opts.stdio : null;
if (stdio && !stdio.includes('ipc')) stdio.push('ipc');
fork(modulePath, args, stdio ? { ...opts, stdio } : opts); Type guard
function hasIpc(stdio: unknown): boolean { return Array.isArray(stdio) && stdio.includes('ipc'); } Try / catch
try { fork(modulePath, args, opts); } catch (e) { if (e.code === 'ERR_CHILD_PROCESS_IPC_REQUIRED') { opts = { ...opts, stdio: [...(opts.stdio ?? []), 'ipc'] }; fork(modulePath, args, opts); } else throw e; } Prevention
- Centralize fork() options in one place and assert the stdio array contains 'ipc'.
- Prefer a stdio string or no stdio option for fork().
When it happens
Trigger: fork(modulePath, args, { stdio: ['ignore', 'pipe', 'pipe'] }). Any stdio array like ['ignore'] or ['pipe', 'pipe'] that omits 'ipc'. Copying a spawn() options object into fork() without changes.
Common situations: Shared process options reused for both spawn() and fork(). Code tuned to silence child output ('ignore') that also drops the IPC entry. Migration from spawn() to fork() for messaging without a stdio review.
Related errors
- ERR_IPC_ONE_PIPE
- ERR_INVALID_ARG_VALUE
- ERR_IPC_SYNC_FORK
- Cannot get 'stderr': 'stderr' is not piped
- Cannot get 'stdout': 'stdout' is not piped
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/8f3576dca41fa49e.
Report an issue: GitHub.
Appendix: 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 != nullView on GitHub (pinned to 9ad36f7a2c)