denoland/deno · error

Invalid handle

Error message

Invalid handle

What it means

During spawn, each stdio slot carrying a raw handle is duplicated into the child with DuplicateHandle. uv_duplicate_handle() first rejects obviously broken values - INVALID_HANDLE_VALUE (-1), NULL, and the -2 sentinel - with InvalidInput 'Invalid handle', because duplicating them would fail or hand the child a garbage stream.

Source

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

  unsafe {
    copy_handle(
      child_stdio_handle(buffer, fd)
        .cast::<HANDLE>()
        .read_unaligned(),
      &mut handle,
    )
  };
  handle
}

pub unsafe fn uv_duplicate_handle(
  handle: HANDLE,
) -> Result<HANDLE, std::io::Error> {
  if handle == INVALID_HANDLE_VALUE
    || handle.is_null()
    || handle == ((-2i32) as usize as HANDLE)
  {
    return Err(std::io::Error::new(
      std::io::ErrorKind::InvalidInput,
      "Invalid handle",
    ));
  }

  let mut dup = INVALID_HANDLE_VALUE;
  let current_process = unsafe { GetCurrentProcess() };

  if unsafe {
    DuplicateHandle(
      current_process,
      handle,
      current_process,
      &mut dup,
      0,
      1,
      DUPLICATE_SAME_ACCESS,
    )

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use supported stdio actions ("pipe", "inherit", "null") instead of raw handles
  2. Ensure any stream or resource passed via stdio is still open at spawn time
  3. Validate handles are not null, -1, or -2 before building the stdio vector
Defensive patterns

Strategy: validation

Validate before calling

function isValidHandle(h: number | null): boolean {
  return typeof h === "number" && h !== 0 && h !== -1 && h !== -2;
}
// validate every raw stdio handle before building the spawn options

Type guard

const isValidRawHandle = (h: unknown): h is number =>
  typeof h === "number" && h !== 0 && h !== -1 && h !== -2;

Prevention

When it happens

Trigger: Passing a closed, null, or sentinel handle in the stdio vector of a spawn: a resource already closed before spawn, an fd of -1 or 0 coming from config defaults, or code that treats Unix fd numbers as Windows handles.

Common situations: Forwarding request/server streams or inherited fds that were closed before the child started; mixing libuv handle values with plain integers; sanitization code that substitutes unknown fds with -1.

Related errors


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