microsoft/aspire · error · InvalidOperationException
Run completed without returning a backchannel.
Error message
Run completed without returning a backchannel.
What it means
PipelineCommandBase awaits a backchannelCompletionSource that the running AppHost task must complete with an auxiliary backchannel. If the run task completes (successfully or faulted) without ever setting a backchannel, ExecuteAsync throws InvalidOperationException, including the run task's exception as InnerException when it faulted.
Solutions
- Check the InnerException / AppHost run output for the underlying startup failure and fix it
- Update the AppHost's Aspire.Hosting packages so it establishes the backchannel (see the related --list-steps incompatibility)
- Rerun 'aspire pipeline' after the AppHost starts successfully; add a hangdump/timeout to diagnose stalls
Example fix
// before aspire pipeline ./MyApp.AppHost/MyApp.AppHost.csproj // after dotnet run --project MyApp.AppHost # first verify the AppHost starts and stays running aspire pipeline ./MyApp.AppHost/MyApp.AppHost.csproj
Defensive patterns
Strategy: try-catch
Validate before calling
// verify the AppHost starts and stays up before running pipelines dotnet run --project MyApp.AppHost & sleep 10 kill %1 # only proceed if startup output showed no errors
Try / catch
try
{
await pipeline.ExecuteAsync(...);
}
catch (InvalidOperationException ex) when (ex.Message == "Run completed without returning a backchannel.")
{
Console.Error.WriteLine($"AppHost run failed before backchannel setup: {ex.InnerException?.Message}");
throw ex.InnerException ?? ex;
} Prevention
- Confirm the AppHost runs cleanly (dotnet run) before 'aspire pipeline'
- Read InnerException for the real startup failure
- Update Aspire.Hosting packages so the run wires up the backchannel
- Use --hangdump/--hangdump-timeout to diagnose handshake stalls
When it happens
Trigger: The AppHost run task finished without publishing a backchannel — the AppHost exited before establishing the auxiliary backchannel, the hosted run failed (faulted task), or an older AppHost never wires the backchannel completion.
Common situations: 'aspire pipeline' against an AppHost that crashes on startup or exits immediately; AppHost version too old to return a backchannel; run cancelled before the backchannel handshake completed.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Already connected to AppHost backchannel.
- Already connected to
- AppHost is incompatible with the CLI. The AppHost must be…
- Cannot reconnect: no previous connection.
- Not connected to auxiliary backchannel.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/767abe3d7c1426f6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Cli/Commands/PipelineCommandBase.cs:322
if (completedTask.IsFaulted && completedTask.Exception?.InnerException is DotNetSdkNotInstalledException sdkException)
{
throw sdkException;
}
// When running in extension context, the extension takes over apphost management.
// DotNetCliRunner returns Success immediately after delegating to LaunchAppHostAsync,
// so pendingRun completes before the backchannel is established. In this case,
// continue waiting for the backchannel rather than throwing.
if (!completedTask.IsFaulted && await pendingRun == CliExitCodes.Success
&& ExtensionHelper.IsExtensionHost(InteractionService, out _, out _))
{
return await backchannelCompletionSource.Task;
}
// Throw an error if the run completed without returning a backchannel.
// Include possible error if the run task faulted.
var innerException = completedTask.IsFaulted ? completedTask.Exception : null;
throw new InvalidOperationException("Run completed without returning a backchannel.", innerException);
}), emoji: KnownEmojis.HammerAndWrench);
// If --list-steps was specified, get pipeline steps and print them instead of executing
if (listSteps)
{
StopTerminalProgressBar();
int inspectionExitCode;
try
{
// Check that the AppHost supports this capability before calling
var capabilities = await backchannel.GetCapabilitiesAsync(cancellationToken);
if (!capabilities.Contains(ListStepsCapability))
{
throw new AppHostIncompatibleException(
ListStepsIncompatibleMessage,
ListStepsCapability);
}View on GitHub (pinned to 25830f84bd)