denoland/deno · error

Could not open NUL device (error {})

Error message

Could not open NUL device (error {})

What it means

After detecting a missing stdio handle, Deno opens the \\?\NUL device so the runtime always has three valid standard streams. If CreateFileA on NUL fails, startup cannot continue and Deno panics with the Win32 error. Opening the null device essentially never fails on a healthy system, so this points to environment-level breakage: handle exhaustion, object-namespace interference, or security software.

Source

Thrown at cli/util/windows.rs:250

          STD_INPUT_HANDLE => FILE_GENERIC_READ,
          _ => FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES,
        };
        let security_attributes = SECURITY_ATTRIBUTES {
          nLength: size_of::<SECURITY_ATTRIBUTES>() as u32,
          lpSecurityDescriptor: std::ptr::null_mut(),
          bInheritHandle: TRUE,
        };
        let file_handle = CreateFileA(
          c"\\\\?\\NUL".as_ptr() as *const u8,
          desired_access,
          FILE_SHARE_READ | FILE_SHARE_WRITE,
          &security_attributes,
          OPEN_EXISTING,
          FILE_ATTRIBUTE_NORMAL,
          std::ptr::null_mut(),
        );
        if file_handle == INVALID_HANDLE_VALUE {
          panic!("Could not open NUL device (error {})", GetLastError());
        }

        // Assign the opened NUL handle to the missing stdio handle.
        if SetStdHandle(std_handle, file_handle) == FALSE {
          panic!("SetStdHandle failed (error {})", GetLastError());
        }
      }
    }
  }
}

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Restart the machine (or the leaky parent process) to clear handle/desktop-heap exhaustion
  2. Temporarily disable or add exclusions for AV/EDR to test interference
  3. Give Deno explicit stdio redirection in the launch command so the NUL fallback is never needed
  4. Capture the error code with `net helpmsg <code>` and report if reproducible on current Deno

Example fix

:: before — inherited closed stdio slot forces the NUL fallback
deno run app.ts

:: after — give every stream a real target
deno run app.ts < NUL > out.log 2>&1
Defensive patterns

Strategy: fallback

Validate before calling

:: pre-flight: give every stream a real target so the NUL fallback never runs
deno run app.ts < NUL > out.log 2>&1

Prevention

When it happens

Trigger: Deno launched with a closed stdio slot while the NUL device open fails — desktop heap/handle exhaustion from a leaking process, restrictive AV/EDR blocking device opens, or a corrupted Windows install.

Common situations: Long-running machines with heavy handle leaks; locked-down corporate endpoints with aggressive EDR; Windows Server Core or sandboxed CI environments with restricted device access.

Related errors


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