microsoft/aspire · error · Win32Exception

Failed to set NUL handle inheritance

Error message

Failed to set NUL handle inheritance

What it means

After opening NUL for a detached child's suppressed stdout/stderr, the handle must be marked inheritable so CreateProcessW can pass it to the child via PROC_THREAD_ATTRIBUTE_HANDLE_LIST. If SetHandleInformation fails, this Win32Exception wrapping the raw Win32 error is thrown. The child has not been spawned yet, so cleanup is trivial.

Solutions

  1. Resolve the upstream 'Failed to open NUL device' failure first — ERROR_INVALID_HANDLE here usually means the open returned a bad handle.
  2. Run the CLI under an unrestricted token; check antivirus/EDR handle-flag interception.
  3. Confirm normal handle inheritance works in the environment with a simple CreateProcess test or `start /b` style commands.
  4. Update the Aspire CLI; escalate with the NativeErrorCode if reproducible on a healthy machine.
Defensive patterns

Strategy: try-catch

Try / catch

try
{
    var process = isolatedProcess.Start(detachedStartInfo);
}
catch (Win32Exception ex) when (ex.Message == "Failed to set NUL handle inheritance")
{
    // Check ex.NativeErrorCode; usually downstream of a failed NUL open or a policy block
}

Prevention

When it happens

Trigger: StartWindowsSuppressed calls WindowsProcessInterop.SetHandleInformation(nulHandle, HandleFlagInherit, HandleFlagInherit) which returns false; GetLastWin32Error typically yields ERROR_INVALID_HANDLE or ERROR_ACCESS_DENIED.

Common situations: Failed/invalid NUL handle from the preceding open step, security software tampering with handle flags, restricted-token environments where handle flag modification is denied.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/9685334e150e985b. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Cli/Processes/IsolatedProcess.Windows.cs:211

    private static StartedProcess StartWindowsSuppressed(IsolatedProcessStartInfo startInfo)
    {
        using var nulHandle = WindowsProcessInterop.CreateFileW(
            "NUL",
            WindowsProcessInterop.GenericWrite,
            WindowsProcessInterop.FileShareWrite,
            nint.Zero,
            WindowsProcessInterop.OpenExisting,
            0,
            nint.Zero);

        if (nulHandle.IsInvalid)
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to open NUL device");
        }

        if (!WindowsProcessInterop.SetHandleInformation(nulHandle, WindowsProcessInterop.HandleFlagInherit, WindowsProcessInterop.HandleFlagInherit))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to set NUL handle inheritance");
        }

        var nulRawHandle = nulHandle.DangerousGetHandle();
        var stdio = new WindowsProcessInterop.StdioHandles(
            Stdin: nint.Zero,
            Stdout: nulRawHandle,
            Stderr: nulRawHandle);

        var pi = WindowsProcessInterop.SpawnProcess(
            startInfo.FileName,
            startInfo.ArgumentList,
            startInfo.WorkingDirectory,
            stdio,
            startInfo.GetEnvironmentForSpawn(),
            createNewConsole: startInfo.IsolateConsole,
            jobHandle: startInfo.KillOnParentExit ? WindowsConsoleProcessJob.Shared.Handle : null);

        SafeProcessHandle? processHandle = new(pi.hProcess, ownsHandle: true);

View on GitHub (pinned to 25830f84bd)