denoland/deno · critical

: ( )

Error message

{}: ({}) {}

What it means

The Windows subprocess runtime ports libuv's fatal-error handling: when a process-control syscall fails, uv_fatal_error_with_no formats the syscall name, errno, and the message from FormatMessage, then panics because the subprocess state cannot be recovered.

Solutions

  1. Verify the executable path exists and is runnable before spawning
  2. Reduce concurrency or check job-object limits on the CI runner
  3. Read the errno in the panic message and map it to the Windows error code (e.g. 5 = access denied) to find the cause
  4. Update Deno - more spawn failures are mapped to typed errors in newer versions
Defensive patterns

Strategy: validation

Validate before calling

// Validate before spawn on Windows
fn spawnable(exe: &str) -> bool {
  let p = std::path::Path::new(exe);
  p.is_file()
}
if !spawnable(&cmd) {
  return Err(format!("executable not found: {cmd}")); // normal error, no panic
}

Prevention

When it happens

Trigger: Spawning a child process on Windows where the OS call fails: invalid spawn attributes or handles, job-object limits reached, or required system resources exhausted in a way not pre-checked by a typed error.

Common situations: Process spawning on constrained CI runners (job limits), antivirus interference, or programmatically produced invalid spawn arguments.

Related errors


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

Appendix: source

Thrown at runtime/subprocess_windows/src/process.rs:189

      0,
      null_mut(),
    );
  }
  let errmsg = if buf.is_null() {
    "Unknown error"
  } else {
    unsafe { CStr::from_ptr(buf).to_str().unwrap() }
  };

  let msg = if syscall.is_empty() {
    format!("({}) {}", errno, errmsg)
  } else {
    format!("{}: ({}) {}", syscall, errno, errmsg)
  };
  if !buf.is_null() {
    unsafe { LocalFree(buf.cast()) };
  }
  panic!("{}", msg);
}

fn uv_fatal_error(syscall: &str) {
  uv_fatal_error_with_no(syscall, None)
}

fn uv_init_global_job_handle() {
  use windows_sys::Win32::System::JobObjects::*;
  UV_GLOBAL_JOB_HANDLE.get_or_init(|| {
    unsafe {
      // SAFETY: SECURITY_ATTRIBUTES is a POD type, repr(C)
      let mut attr = mem::zeroed::<SECURITY_ATTRIBUTES>();
      // SAFETY: JOBOBJECT_EXTENDED_LIMIT_INFORMATION is a POD type, repr(C)
      let mut info = mem::zeroed::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>();
      attr.bInheritHandle = FALSE;

      info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_BREAKAWAY_OK
        | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK

View on GitHub (pinned to 9ad36f7a2c)