microsoft/aspire · error · InvalidOperationException
Cannot reconnect: no previous connection.
Error message
Cannot reconnect: no previous connection.
What it means
AppHostCliBackchannel can reconnect to a new AppHost process only if it remembers the Unix domain socket path from a previous connection. When ReconnectInternalAsync runs (triggered from OnDisconnected) before any connection was ever established, the socket path is null, so the CLI throws this InvalidOperationException rather than attempting a reconnect to an unknown target.
Solutions
- Ensure the initial connection is established (and thus _socketPath is set) before disconnect/reconnect handling is subscribed to or can fire.
- Guard reconnect logic: check whether the backchannel has ever connected before attempting reconnection.
- If the AppHost died before connecting, treat it as a fresh start (start/restart the AppHost and connect anew) rather than a reconnect.
Example fix
// before
await backchannel.ReconnectInternalAsync();
// after
if (backchannel.HasEverConnected)
{
await backchannel.ReconnectInternalAsync();
}
else
{
await backchannel.ConnectAsync(cancellationToken);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (backchannel is not { HasEverConnected: true }) { /* treat as fresh connect, not reconnect */ } Type guard
bool canReconnect = backchannel is { HasEverConnected: true }; Try / catch
try { await backchannel.ReconnectInternalAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("no previous connection"))
{ await backchannel.ConnectAsync(ct); } Prevention
- Always complete the initial ConnectAsync before subscribing to disconnect events.
- Track connection state explicitly so reconnect is never attempted on a never-connected channel.
- Treat 'AppHost died before connect' as a restart scenario, not a reconnect.
When it happens
Trigger: A disconnect notification (OnDisconnected) fires on the backchannel before any successful ConnectAsync completed, so _socketPath was never populated. Calling ReconnectInternalAsync directly on a freshly constructed AppHostCliBackchannel also throws this.
Common situations: The AppHost process dies or drops the socket very early in CLI startup, racing with the initial connect; a consumer calls reconnect logic before the first connection; a race between disconnect events and connection establishment.
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
- Already connected to
- Already connected to AppHost backchannel.
- AppHost is incompatible with the CLI. The AppHost must be…
- Not connected to auxiliary backchannel.
- Resource update buffering was not enabled for this watcher.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/b6adaab0e08135b0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Cli/Backchannel/AppHostCliBackchannel.cs:448
{
_disconnectTaskCompletionSource.TrySetResult();
}
}
private void ResetForReconnection()
{
lock (_lock)
{
logger.LogDebug("Resetting backchannel for reconnection");
_rpcTaskCompletionSource = new TaskCompletionSource<JsonRpc>();
}
}
private async Task ReconnectInternalAsync()
{
if (_socketPath is null)
{
throw new InvalidOperationException("Cannot reconnect: no previous connection.");
}
ResetForReconnection();
// Wait for the new socket to appear (the new DistributedApplication needs to start)
var startTime = DateTime.UtcNow;
var maxWait = TimeSpan.FromSeconds(30);
var retryCount = 0;
while (!_cancellationToken.IsCancellationRequested)
{
try
{
await ConnectAsync(_socketPath, _autoReconnect, retryCount, _cancellationToken).ConfigureAwait(false);
logger.LogInformation("Successfully reconnected to backchannel");
return;
}
catch (SocketException) when (DateTime.UtcNow - startTime < maxWait)View on GitHub (pinned to 25830f84bd)