{"record":{"id":"8f3576dca41fa49e","repo":"denoland/deno","slug":"err-child-process-ipc-required","errorCode":"ERR_CHILD_PROCESS_IPC_REQUIRED","errorMessage":"Forked processes must have an IPC channel, missing value 'ipc' in options.stdio","messagePattern":"Forked processes must have an IPC channel, missing value 'ipc' in options\\.stdio","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/child_process.ts","lineNumber":285,"sourceCode":"    if (result.traceEventCategories) {\n      options.env = {\n        ...(options.env ?? lazyProcess().default.env),\n        DENO_NODE_TRACE_EVENT_CATEGORIES: result.traceEventCategories,\n      };\n    }\n  }\n\n  if (typeof options.stdio === \"string\") {\n    options.stdio = stdioStringToArray(options.stdio, \"ipc\");\n  } else if (!ArrayIsArray(options.stdio)) {\n    // Use a separate fd=3 for the IPC channel. Inherit stdin, stdout,\n    // and stderr from the parent if silent isn't set.\n    options.stdio = stdioStringToArray(\n      options.silent ? \"pipe\" : \"inherit\",\n      \"ipc\",\n    );\n  } else if (!ArrayPrototypeIncludes(options.stdio, \"ipc\")) {\n    throw new ERR_CHILD_PROCESS_IPC_REQUIRED(\"options.stdio\");\n  }\n\n  options.execPath = options.execPath || Deno.execPath();\n  options.shell = false;\n\n  // deno-lint-ignore no-explicit-any\n  (options as any)[kNeedsNpmProcessState] = true;\n\n  return spawn(options.execPath, args, options);\n}\n\nfunction spawn(\n  command: string,\n  argsOrOptions?: string[] | SpawnOptions,\n  maybeOptions?: SpawnOptions,\n): ChildProcess {\n  const args = ArrayIsArray(argsOrOptions) ? argsOrOptions : [];\n  let options = !ArrayIsArray(argsOrOptions) && argsOrOptions != null","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/node/polyfills/child_process.ts#L267-L303","documentation":"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.","triggerScenarios":"fork('child.js', [], { stdio: ['pipe', 'pipe', 'pipe'] }); fork(modulePath, { stdio: ['ignore', 'inherit', 'inherit'] }); any fork with a custom stdio array lacking 'ipc'.","commonSituations":"Copying a spawn stdio configuration into fork; trying to silence child output with an explicit array and unintentionally dropping the IPC entry.","solutions":["Append 'ipc' as the fourth stdio entry: { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] }","Use the string shorthand { stdio: 'pipe' } which auto-adds the IPC channel","If no messaging between processes is needed, use spawn() instead of fork()"],"exampleFix":"// before\nfork('child.js', [], { stdio: ['pipe', 'pipe', 'pipe'] });\n// after\nfork('child.js', [], { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] });","handlingStrategy":"validation","validationCode":"if (Array.isArray(options.stdio) && !options.stdio.includes('ipc')) {\n  options.stdio = [...options.stdio, 'ipc'];\n}\nfork(modulePath, [], options);","typeGuard":"const stdioHasIpc = (stdio) => typeof stdio === 'string' || (Array.isArray(stdio) && stdio.includes('ipc'));","tryCatchPattern":null,"preventionTips":["Prefer the string stdio shorthand with fork; ipc is added for you","When using a stdio array with fork, budget one slot for 'ipc'","Use spawn when no IPC messaging is required"],"tags":["child-process","fork","ipc","node-compat"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}