diff --git a/clients/shared/Network/EventStreamClient.swift b/clients/shared/Network/EventStreamClient.swift index 875722f73b4..e42ead28e90 100644 --- a/clients/shared/Network/EventStreamClient.swift +++ b/clients/shared/Network/EventStreamClient.swift @@ -277,6 +277,15 @@ public final class EventStreamClient { sseTask = Task { @MainActor [weak self] in guard let self else { return } + // A back-to-back call to `startSSEStream()` on the MainActor can + // cancel this task and invalidate `session` before it runs its + // first instruction. Calling `session.bytes(for:)` on an already + // invalidated session throws an ObjC NSGenericException from + // `-[__NSURLSessionLocal taskForClassInfo:]`, which is + // uncatchable in Swift and crashes the process with SIGABRT. + // Bail out before touching the session if we've been superseded. + guard !Task.isCancelled, self.sseSession === session else { return } + do { let (bytes, response) = try await GatewayHTTPClient.stream( path: "assistants/{assistantId}/events",