denoland/deno · error · TypeError

ERR_INVALID_ARG_VALUE

ERR_INVALID_ARG_VALUE

Error message

The argument 'stdio' is invalid. Received ${inspected}

What it means

In Deno's node:child_process polyfill, stdioStringToArray() expands a shorthand string stdio option into the 3-element array [stdio, stdio, stdio]. Only 'ignore', 'overlapped', 'pipe' and 'inherit' are accepted; any other string falls to the default branch and throws ERR_INVALID_ARG_VALUE. This runs on the fork()/spawn option-normalization path.

Source

Thrown at ext/node/polyfills/internal/child_process.ts:209

}

function stdioStringToArray(
  stdio,
  channel,
) {
  const options = [];

  switch (stdio) {
    case "ignore":
    case "overlapped":
    case "pipe":
      ArrayPrototypePush(options, stdio, stdio, stdio);
      break;
    case "inherit":
      ArrayPrototypePush(options, stdio, stdio, stdio);
      break;
    default:
      throw new ERR_INVALID_ARG_VALUE("stdio", stdio);
  }

  if (channel) ArrayPrototypePush(options, channel);

  return options;
}

const kClosesNeeded = Symbol("_closesNeeded");
const kClosesReceived = Symbol("_closesReceived");
const kCanDisconnect = Symbol("_canDisconnect");
const kChildStdioUsedAsInput = Symbol("childStdioUsedAsInput");
const childStdioStreamsByFd = new SafeMap();
let emittedShellDeprecation = false;

// We only want to emit a close event for the child process when all of
// the writable streams have closed. The value of `child[kClosesNeeded]` should be 1 +
// the number of opened writable streams (note this excludes `stdin`).
function maybeClose(child) {

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use one of the four valid strings: 'pipe', 'inherit', 'ignore', 'overlapped'
  2. For IPC use the array form, e.g. stdio: ['ipc', 'pipe', 'pipe'], or just call fork() which wires IPC for you
  3. For per-fd control pass a full array: stdio: ['inherit', 'pipe', 'ignore']
  4. Trim/validate the string before passing if it comes from user input or config

Example fix

// before
fork(script, { stdio: 'silent' });

// after
fork(script, { silent: true });
// or
fork(script, { stdio: ['ignore', 'pipe', 'pipe'] });
Defensive patterns

Strategy: validation

Validate before calling

const VALID = new Set(['pipe', 'inherit', 'ignore', 'overlapped']);
function toStdioArray(shorthand) {
  if (typeof shorthand === 'string' && !VALID.has(shorthand)) {
    throw new Error(`invalid stdio shorthand '${shorthand}'; expected one of ${[...VALID].join(', ')}`);
  }
  return typeof shorthand === 'string' ? [shorthand, shorthand, shorthand] : shorthand;
}

Type guard

const isStdioShorthand = (s) => typeof s === 'string' &&
  ['pipe', 'inherit', 'ignore', 'overlapped'].includes(s);

Try / catch

try { fork(script, { stdio: mode }); } catch (err) {
  if (err?.code === 'ERR_INVALID_ARG_VALUE' && /stdio/.test(err.message)) {
    // fall back to explicit array form
    fork(script, { stdio: ['pipe', 'pipe', 'pipe'] });
  }
}

Prevention

When it happens

Trigger: fork(modulePath, { stdio: 'ipc' }), stdio: 'silent', stdio: 'null', stdio: 'inherit ' (trailing space), or any typo'd keyword — i.e. any string shorthand outside the four valid values.

Common situations: Confusing spawn's legacy `silent: true` boolean with a stdio string; writing stdio: 'null' instead of 'ignore'; trying to request an IPC channel with the string 'ipc' (only valid as an array element); values built by string concatenation that pick up whitespace.

Related errors


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