{"record":{"id":"b6adaab0e08135b0","repo":"microsoft/aspire","slug":"cannot-reconnect-no-previous-connection","errorCode":null,"errorMessage":"Cannot reconnect: no previous connection.","messagePattern":"Cannot reconnect: no previous connection\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Cli/Backchannel/AppHostCliBackchannel.cs","lineNumber":448,"sourceCode":"        {\n            _disconnectTaskCompletionSource.TrySetResult();\n        }\n    }\n\n    private void ResetForReconnection()\n    {\n        lock (_lock)\n        {\n            logger.LogDebug(\"Resetting backchannel for reconnection\");\n            _rpcTaskCompletionSource = new TaskCompletionSource<JsonRpc>();\n        }\n    }\n\n    private async Task ReconnectInternalAsync()\n    {\n        if (_socketPath is null)\n        {\n            throw new InvalidOperationException(\"Cannot reconnect: no previous connection.\");\n        }\n\n        ResetForReconnection();\n\n        // Wait for the new socket to appear (the new DistributedApplication needs to start)\n        var startTime = DateTime.UtcNow;\n        var maxWait = TimeSpan.FromSeconds(30);\n\n        var retryCount = 0;\n        while (!_cancellationToken.IsCancellationRequested)\n        {\n            try\n            {\n                await ConnectAsync(_socketPath, _autoReconnect, retryCount, _cancellationToken).ConfigureAwait(false);\n                logger.LogInformation(\"Successfully reconnected to backchannel\");\n                return;\n            }\n            catch (SocketException) when (DateTime.UtcNow - startTime < maxWait)","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Cli/Backchannel/AppHostCliBackchannel.cs#L430-L466","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait backchannel.ReconnectInternalAsync();\n\n// after\nif (backchannel.HasEverConnected)\n{\n    await backchannel.ReconnectInternalAsync();\n}\nelse\n{\n    await backchannel.ConnectAsync(cancellationToken);\n}","handlingStrategy":"try-catch","validationCode":"if (backchannel is not { HasEverConnected: true }) { /* treat as fresh connect, not reconnect */ }","typeGuard":"bool canReconnect = backchannel is { HasEverConnected: true };","tryCatchPattern":"try { await backchannel.ReconnectInternalAsync(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"no previous connection\"))\n{ await backchannel.ConnectAsync(ct); }","preventionTips":["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."],"tags":["backchannel","reconnection","invalid-state","cli"],"backgroundTag":"invalid-state-transition","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}