{"record":{"id":"8ed0877dad4749a1","repo":"denoland/deno","slug":"err-ipc-one-pipe","errorCode":"ERR_IPC_ONE_PIPE","errorMessage":"Child process can have only one IPC pipe","messagePattern":"Child process can have only one IPC pipe","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/child_process.ts","lineNumber":435,"sourceCode":"    const argv0 = args.length > 0 ? args[0] : command;\n    const builtCommand = buildCommand(\n      command,\n      ArrayPrototypeSlice(args, 1),\n      env,\n    );\n    const cmd = builtCommand[0];\n    const cmdArgs = builtCommand[1];\n    const includeNpmProcessState = builtCommand[2];\n\n    this.spawnfile = cmd;\n    this.spawnargs = [cmd, ...new SafeArrayIterator(cmdArgs)];\n\n    const ipc = ArrayPrototypeIndexOf(normalizedStdio, \"ipc\");\n    if (\n      ipc !== -1 &&\n      ArrayPrototypeIndexOf(normalizedStdio, \"ipc\", ipc + 1) !== -1\n    ) {\n      throw new ERR_IPC_ONE_PIPE();\n    }\n\n    const extraStdioOffset = 3; // stdin, stdout, stderr\n\n    const extraStdioNormalized = [];\n    for (let i = 0; i < extraStdio.length; i++) {\n      const fd = i + extraStdioOffset;\n      if (fd === ipc) {\n        // IPC fd is handled separately in Rust via the kIpc option.\n        // Push a placeholder so the array indices stay aligned with\n        // fd numbers, but don't double-push.\n        ArrayPrototypePush(extraStdioNormalized, \"null\");\n        continue;\n      }\n      ArrayPrototypePush(extraStdioNormalized, toDenoStdio(extraStdio[i]));\n    }\n\n    // Windows does not support uid/gid options - throw ENOTSUP synchronously.","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/child_process.ts#L417-L453","documentation":"ERR_IPC_ONE_PIPE is thrown when the normalized stdio array contains the 'ipc' entry more than once. A child process can have exactly one IPC channel; each 'ipc' slot maps to the single kIpc option handed to the Rust spawn layer, so a second one is rejected before process creation.","triggerScenarios":"spawn(cmd, args, { stdio: ['ipc', 'ipc', 'pipe'] }); manually adding 'ipc' to stdio while also passing options.serialization/stdio handling that already includes it; fork()-style usage where a channel is appended on top of a stdio array that already contains 'ipc'.","commonSituations":"Copy-pasting a fork stdio preset like ['ipc', 'pipe', 'pipe', 'ipc'] (an extra entry for fd 3); merging user stdio with IPC defaults via array concat producing duplicates; upgrading code from spawn() to fork() without removing the manual 'ipc' entry.","solutions":["Include 'ipc' exactly once in the stdio array, e.g. ['ipc', 'pipe', 'pipe']","Prefer fork() which manages the IPC entry for you — don't also hand it a manual 'ipc'","Dedupe before spawn: new Set(stdio).has('ipc') count check, keep only the first occurrence"],"exampleFix":"// before\nspawn(process.execPath, [script], { stdio: ['ipc', 'pipe', 'pipe', 'ipc'] });\n\n// after\nspawn(process.execPath, [script], { stdio: ['ipc', 'pipe', 'pipe'] });","handlingStrategy":"validation","validationCode":"function withSingleIpc(stdio) {\n  const first = stdio.indexOf('ipc');\n  if (first === -1) return stdio;\n  if (stdio.indexOf('ipc', first + 1) !== -1) {\n    throw new Error('stdio may contain at most one \\'ipc\\' entry');\n  }\n  return stdio;\n}","typeGuard":"const hasSingleIpc = (stdio) => stdio.filter((s) => s === 'ipc').length <= 1;","tryCatchPattern":"try { spawn(cmd, args, { stdio }); } catch (err) {\n  if (err?.code === 'ERR_IPC_ONE_PIPE') {\n    const first = stdio.indexOf('ipc');\n    spawn(cmd, args, { stdio: stdio.map((s, i) => s === 'ipc' && i !== first ? 'pipe' : s) });\n  }\n}","preventionTips":["Let fork() own the IPC entry; don't add 'ipc' yourself on top of it","Keep 'ipc' at one slot (conventionally index 0 or 3+), never repeated","When merging user stdio with defaults, dedupe 'ipc' before spawning"],"tags":["child-process","ipc","stdio","node-compat","deno","fork"],"backgroundTag":"invalid-stdio-option","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}