diff --git a/src/Aspire.Cli/Backchannel/AppHostBackchannel.cs b/src/Aspire.Cli/Backchannel/AppHostBackchannel.cs index c605bcf02e0..b745e380131 100644 --- a/src/Aspire.Cli/Backchannel/AppHostBackchannel.cs +++ b/src/Aspire.Cli/Backchannel/AppHostBackchannel.cs @@ -88,38 +88,49 @@ await rpc.InvokeWithCancellationAsync( public async Task ConnectAsync(Process process, string socketPath, CancellationToken cancellationToken) { - using var activity = _activitySource.StartActivity(); - - _process = process; - - if (_rpcTaskCompletionSource.Task.IsCompleted) + try { - throw new InvalidOperationException("Already connected to AppHost backchannel."); + using var activity = _activitySource.StartActivity(); + + _process = process; + + if (_rpcTaskCompletionSource.Task.IsCompleted) + { + throw new InvalidOperationException("Already connected to AppHost backchannel."); + } + + logger.LogDebug("Connecting to AppHost backchannel at {SocketPath}", socketPath); + var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); + var endpoint = new UnixDomainSocketEndPoint(socketPath); + await socket.ConnectAsync(endpoint, cancellationToken); + logger.LogDebug("Connected to AppHost backchannel at {SocketPath}", socketPath); + + var stream = new NetworkStream(socket, true); + var rpc = JsonRpc.Attach(stream, target); + + var capabilities = await rpc.InvokeWithCancellationAsync( + "GetCapabilitiesAsync", + Array.Empty(), + cancellationToken); + + if (!capabilities.Any(s => s == "baseline.v0")) + { + throw new AppHostIncompatibleException( + $"AppHost is incompatible with the CLI. The AppHost must be updated to a version that supports the baseline.v0 capability.", + "baseline.v0" + ); + } + + _rpcTaskCompletionSource.SetResult(rpc); } - - logger.LogDebug("Connecting to AppHost backchannel at {SocketPath}", socketPath); - var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); - var endpoint = new UnixDomainSocketEndPoint(socketPath); - await socket.ConnectAsync(endpoint, cancellationToken); - logger.LogDebug("Connected to AppHost backchannel at {SocketPath}", socketPath); - - var stream = new NetworkStream(socket, true); - var rpc = JsonRpc.Attach(stream, target); - - var capabilities = await rpc.InvokeWithCancellationAsync( - "GetCapabilitiesAsync", - Array.Empty(), - cancellationToken); - - if (!capabilities.Any(s => s == "baseline.v0")) + catch (RemoteMethodNotFoundException ex) { + logger.LogError(ex, "Failed to connect to AppHost backchannel. The AppHost must be updated to a version that supports the baseline.v0 capability."); throw new AppHostIncompatibleException( $"AppHost is incompatible with the CLI. The AppHost must be updated to a version that supports the baseline.v0 capability.", "baseline.v0" ); } - - _rpcTaskCompletionSource.SetResult(rpc); } public async Task GetPublishersAsync(CancellationToken cancellationToken) diff --git a/src/Aspire.Cli/DotNetCliRunner.cs b/src/Aspire.Cli/DotNetCliRunner.cs index e8d947d1f12..97d318fb952 100644 --- a/src/Aspire.Cli/DotNetCliRunner.cs +++ b/src/Aspire.Cli/DotNetCliRunner.cs @@ -486,6 +486,12 @@ private async Task StartBackchannelAsync(Process process, string socketPath, Tas throw; } + catch (Exception ex) + { + logger.LogError(ex, "An unexpected error occurred while trying to connect to the backchannel."); + backchannelCompletionSource.SetException(ex); + throw; + } } while (await timer.WaitForNextTickAsync(cancellationToken)); }