microsoft/aspire · error · InvalidOperationException

Not connected to auxiliary backchannel.

Error message

Not connected to auxiliary backchannel.

What it means

AppHostAuxiliaryBackchannel.EnsureConnected returns the active JsonRpc instance but throws if the backchannel has never connected or was disposed. Callers of RPC methods must have completed ConnectAsync first. This is a state-check guard: you are invoking a backchannel RPC without an established connection.

Solutions

  1. Call and await ConnectAsync (with the correct socket path) before issuing any RPC calls.
  2. Check that the AppHost process is running and its auxiliary backchannel socket exists before connecting.
  3. Guard call sites so RPCs are only attempted after a successful connect (check the connection task/state).
  4. Recreate the backchannel instance and reconnect if a previous connection attempt failed.

Example fix

// before
var backchannel = new AppHostAuxiliaryBackchannel();
var result = await backchannel.RequestSomethingAsync(); // throws
// after
var backchannel = new AppHostAuxiliaryBackchannel();
await backchannel.ConnectAsync(socketPath, ...);
var result = await backchannel.RequestSomethingAsync();
Defensive patterns

Strategy: try-catch

Try / catch

try
{
    await backchannel.RequestAsync(...);
}
catch (InvalidOperationException ex) when (ex.Message == "Not connected to auxiliary backchannel.")
{
    await backchannel.ConnectAsync(socketPath, ...); // connect once, then retry
}

Prevention

When it happens

Trigger: Thrown when any RPC operation calls EnsureConnected while the private _rpc field is null — i.e. methods are invoked before ConnectAsync completed, after a failed connect, or after the instance was created but never connected.

Common situations: Calling auxiliary backchannel APIs before awaiting ConnectAsync; connection setup failed earlier (socket absent, AppHost not ready) and the error surfaces later on first RPC; constructing the backchannel manually in tests/tools without connecting it.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Cli/Backchannel/AppHostAuxiliaryBackchannel.cs:119

    /// <inheritdoc />
    public bool SupportsResourceSnapshotVersionsV1 => _capabilities.Contains(AuxiliaryBackchannelCapabilities.ResourceSnapshotVersions_V1);

    /// <summary>
    /// Gets the JSON-RPC proxy for communicating with the AppHost.
    /// </summary>
    internal JsonRpc? Rpc => _rpc;

    /// <summary>
    /// Ensures the connection is valid and returns the RPC proxy.
    /// </summary>
    /// <exception cref="ObjectDisposedException">Thrown if the object has been disposed.</exception>
    /// <exception cref="InvalidOperationException">Thrown if not connected to the backchannel.</exception>
    private JsonRpc EnsureConnected()
    {
        ObjectDisposedException.ThrowIf(_disposed, this);
        if (_rpc is null)
        {
            throw new InvalidOperationException("Not connected to auxiliary backchannel.");
        }
        return _rpc;
    }

    /// <summary>
    /// Creates and connects a new auxiliary backchannel to the specified socket.
    /// </summary>
    /// <param name="appHostSocket">The AppHost socket to connect to.</param>
    /// <param name="logger">Logger for diagnostic messages.</param>
    /// <param name="profilingTelemetry">Profiling service.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A connected AppHostAuxiliaryBackchannel instance.</returns>
    public static Task<AppHostAuxiliaryBackchannel> ConnectAsync(
        IAppHostSocket appHostSocket,
        ILogger logger,
        ProfilingTelemetry profilingTelemetry,
        CancellationToken cancellationToken = default)
    {

View on GitHub (pinned to 25830f84bd)