denoland/deno · error

Invalid stdio count

Error message

Invalid stdio count

What it means

uv_stdio_create() sizes the child's stdio buffer from options.stdio. libuv/CreateProcess support at most 255 streams, so a stdio vector longer than 255 entries is rejected up front with InvalidInput 'Invalid stdio count' (vectors shorter than 3 are padded up to stdin/stdout/stderr).

Source

Thrown at runtime/subprocess_windows/src/process_stdio.rs:253

      size_of::<HANDLE>(),
    )
  }
}

#[derive(Debug, Clone, Copy)]
pub enum StdioContainer {
  Ignore,
  InheritFd(i32),
  RawHandle(HANDLE),
}

#[inline(never)]
pub(crate) fn uv_stdio_create(
  options: &SpawnOptions,
) -> Result<StdioBuffer, std::io::Error> {
  let mut count = options.stdio.len();
  if count > 255 {
    return Err(std::io::Error::new(
      std::io::ErrorKind::InvalidInput,
      "Invalid stdio count",
    ));
  } else if count < 3 {
    count = 3;
  }

  let mut buffer = StdioBuffer::new(count);

  for i in 0..count {
    let fdopt = if i < options.stdio.len() {
      options.stdio[i]
    } else {
      StdioContainer::Ignore
    };

    match fdopt {
      StdioContainer::RawHandle(handle) => {

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Trim the stdio vector to the streams you actually use (normally 3: stdin, stdout, stderr)
  2. Fix the loop that generates one stdio entry per item
  3. Pass extra data through files or pipes set up after spawn instead of extra stdio slots

Example fix

// before
const stdio = openFiles.map(() => "pipe"); // 300 entries
spawn(prog, { stdio: ["pipe", "pipe", "pipe", ...stdio] });

// after
spawn(prog, { stdio: ["pipe", "pipe", "pipe"] });
Defensive patterns

Strategy: validation

Validate before calling

if (stdio.length > 255) {
  throw new Error(`stdio count ${stdio.length} exceeds the Windows limit of 255`);
}

Type guard

const isWithinStdioLimit = (stdio: unknown[]): stdio is unknown[] =>
  stdio.length <= 255;

Prevention

When it happens

Trigger: Spawning with a stdio array longer than 255 entries - reachable from Node-compat child_process.spawn({ stdio: [...many] }) or from programmatic code that generates one stdio entry per open file.

Common situations: A loop bug that appends one "pipe" per iteration; porting code that wires dozens or hundreds of fds into a child; copy-paste expansion of stdio configuration arrays.

Related errors


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