dotnet/reactive · error · InvalidOperationException

Did not get output from program

Error message

Did not get output from program

What it means

While running the test app process, RunScenarioAsync awaits both stdout and stderr tasks, polling with Task.WhenAny + Task.Delay(2000). If stdout never completes it throws InvalidOperationException('Did not get output from program'). The child process produced no terminating stdout within the wait loop, typically because it hung or crashed.

Solutions

  1. Run the test app manually with the same arguments to see why stdout never completes
  2. Check for deadlocks or Console.ReadLine/waiting on stdin in the test app
  3. Ensure both stdout and stderr are read concurrently so pipe buffers do not block the child
  4. Increase the polling timeout if the app is legitimately slow to start
Defensive patterns

Strategy: try-catch

Validate before calling

var psi = new ProcessStartInfo(appExe) { RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false };
using var p = Process.Start(psi);
if (p is null) throw new InvalidOperationException("App process failed to start");

Type guard

bool StdOutDone(Task t, int ms) => Task.WaitAny(new[]{t}, ms) != -1;

Try / catch

try
{
    await check.RunScenarioAsync(...);
}
catch (InvalidOperationException ex) when (ex.Message == "Did not get output from program")
{
    // kill hung process, log, mark scenario failed
}

Prevention

When it happens

Trigger: The launched test-app process blocks or exits without closing/flushing stdout, leaving stdOutTask incomplete when the polling loop stops.

Common situations: Test app deadlocks (e.g., waiting on console input); process crashes before writing output; the app writes huge output causing pipe backpressure if not drained correctly; machine slowness.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/aee63018f8bf2c5a. Report an issue: GitHub.

Appendix: source

Thrown at Rx.NET/Test/Gauntlet/Checks/TransitiveReferences/CheckTransitiveFrameworkReference/RunTransitiveFrameworkReferenceCheck.cs:282

                    var stdOutTask = Task.Run(process.StandardOutput.ReadToEndAsync);
                    var stdErrTask = Task.Run(process.StandardError.ReadToEndAsync);
                    var processTask = process.WaitForExitAsync();
                    var firstToFinish = await Task.WhenAny(processTask, stdOutTask, stdErrTask);

                    if (!stdOutTask.IsCompleted)
                    {
                        // The process finished, but the standard output task is still running. It's possible that
                        // it is nearly done, so give it some time.
                        await Task.WhenAny(stdOutTask, Task.Delay(2000));
                    }
                    if (!stdErrTask.IsCompleted)
                    {
                        await Task.WhenAny(stdErrTask, Task.Delay(2000));
                    }

                    if (!stdOutTask.IsCompleted)
                    {
                        throw new InvalidOperationException("Did not get output from program");
                    }

                    if (!stdErrTask.IsCompleted)
                    {
                        throw new InvalidOperationException("Did not get error output from program");
                    }
                    runStdOut = await stdOutTask;
                    runStdErr = await stdErrTask;

                    await processTask;
                    runExitCode = process.ExitCode;
                }
#pragma warning restore IDE0063 // Use simple 'using' statement
            }
            else
            {
                //Debugger.Break();
                Console.WriteLine(r.BuildStdOut);

View on GitHub (pinned to 94b5d5ab91)