From d2633fb92de269d28be9b0aa00e789ae23d418c2 Mon Sep 17 00:00:00 2001 From: Alan Wizemann Date: Fri, 24 Apr 2026 14:44:18 +0200 Subject: [PATCH] M7 #16 (pass-2): don't bubble CancellationError into the chat banner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass-2 observed a spurious "The operation couldn't be completed. (Swift.CancellationError error 1)" banner appearing even after the resumed session loaded cleanly. Root cause: when ChatController.startResuming tears down a prior live session via `await stop()`, the in-flight event-task awaits throw CancellationError as they unwind — that's how Swift concurrency cooperatively cancels. That error then propagated through recordACPFailure to the visible banner, even though nothing actually failed. Filter CancellationError (and the URL-loading equivalent, NSURLErrorCancelled) out at the recordACPFailure boundary. Real errors still flow through to the banner with hints + stderr details. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ScarfCore/ViewModels/RichChatViewModel.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scarf/Packages/ScarfCore/Sources/ScarfCore/ViewModels/RichChatViewModel.swift b/scarf/Packages/ScarfCore/Sources/ScarfCore/ViewModels/RichChatViewModel.swift index d272431..5c03195 100644 --- a/scarf/Packages/ScarfCore/Sources/ScarfCore/ViewModels/RichChatViewModel.swift +++ b/scarf/Packages/ScarfCore/Sources/ScarfCore/ViewModels/RichChatViewModel.swift @@ -120,7 +120,19 @@ public final class RichChatViewModel { /// Populate the error triplet from a thrown Error + the ACPClient /// we can query for recent stderr. Safe to call from anywhere /// that catches an ACP op failure. + /// + /// Swallows `CancellationError` silently — it's how Swift's task + /// tree signals cooperative cleanup (e.g. when startResuming + /// tears down a prior live session via stop(), the event-task + /// awaits throw as they unwind). That's expected plumbing, not a + /// user-visible failure — showing "The operation couldn't be + /// completed (Swift.CancellationError)" in the chat banner would + /// alarm users whose session actually loaded fine. Pass-2 UX fix. public func recordACPFailure(_ error: Error, client: ACPClient?) async { + if error is CancellationError { return } + if (error as NSError).domain == NSURLErrorDomain, (error as NSError).code == NSURLErrorCancelled { + return + } let msg = error.localizedDescription let stderrTail = await client?.recentStderr ?? "" let hint = ACPErrorHint.classify(errorMessage: msg, stderrTail: stderrTail)