@@ -76,6 +76,7 @@ struct AlertsView: View {
77 private func loadAlerts(stream: String) async {
77 private func loadAlerts(stream: String) async {
78 guard let client = appState.client else { return }
78 guard let client = appState.client else { return }
79+ let connID = appState.activeConnection?.id
79 isLoading = true
80 isLoading = true
80 errorMessage = nil
81 errorMessage = nil
81 alertConfig = nil
82 alertConfig = nil
@@ -84,13 +85,17 @@ struct AlertsView: View {
84 let config = try await client.getAlerts(stream: stream)
85 let config = try await client.getAlerts(stream: stream)
85 // The manual Refresh/Retry buttons spawn detached Tasks not tied to
86 // The manual Refresh/Retry buttons spawn detached Tasks not tied to
86 // `.task(id: stream)` cancellation, so a slow refresh for the old stream
87 // `.task(id: stream)` cancellation, so a slow refresh for the old stream
87− // can resolve after a switch. Drop stale results.
88+ // can resolve after a switch. Drop stale results. Check the connection
89+ // id too: two servers can expose a same-named stream, so a name-only
90+ // guard could write the previous server's alerts after a server switch.
88 // Still clear isLoading on the stale path: this task set the spinner,
91 // Still clear isLoading on the stale path: this task set the spinner,
89 // so leaving it true wedges the ProgressView and disables Refresh.
92 // so leaving it true wedges the ProgressView and disables Refresh.
90− guard stream == appState.selectedStream else { isLoading = false; return }
93+ guard stream == appState.selectedStream,
94+ connID == appState.activeConnection?.id else { isLoading = false; return }
91 alertConfig = config
95 alertConfig = config
93− guard stream == appState.selectedStream else { isLoading = false; return }
97+ guard stream == appState.selectedStream,
98+ connID == appState.activeConnection?.id else { isLoading = false; return }
94 errorMessage = ParseableError.userFriendlyMessage(for: error)
99 errorMessage = ParseableError.userFriendlyMessage(for: error)