Closed AndrewSB closed 2 years ago
Thanks for reporting @AndrewSB. I've moved this to our main repo, since it's most likely in the low-level client. We will analyze it and get back when we have more info.
Hello everyone ! Same for us 👇🏻
Seems to be related to the latest release 4.20, no issues with >4.20
@AndrewSB @Aurazion, can you guys provide more info about the crash? Do you know how to reproduce? Can you also share the full stack trace of the crash?
Best, Nuno
Hi @nuno-vieira, it occurs directly after the app opening, it completely freeze the whole app, and crash when the app is killed or after a few minutes.
Thread 1
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
* frame #0: 0x0000000118073bdc libsystem_kernel.dylib`__psynch_mutexwait + 8
frame #1: 0x0000000118114aac libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_wait + 80
frame #2: 0x00000001181125d8 libsystem_pthread.dylib`_pthread_mutex_firstfit_lock_slow + 244
frame #3: 0x00000001070104e4 Foundation`-[NSRecursiveLock lock] + 24
frame #4: 0x000000010c456528 StreamChat`specialized Cached.reset() [inlined] generic specialization <Swift.Optional<StreamChat.LazyCachedMapCollection<StreamChat.ChatChannelMember>>> of StreamChat.Atomic.mutate(self=0x0000600003a7c210) -> ()) -> () at Atomic.swift:45:14 [opt]
frame #5: 0x000000010c45651c StreamChat`specialized Cached.reset() [inlined] generic specialization <Swift.Optional<StreamChat.LazyCachedMapCollection<StreamChat.ChatChannelMember>>> of StreamChat.Atomic.wrappedValue.setter : τ_0_0(newValue=nil, self=0x0000600003a7c210) at Atomic.swift:35:13 [opt]
frame #6: 0x000000010c45651c StreamChat`specialized Cached.reset(self=<unavailable>) at Cached.swift:48:17 [opt]
frame #7: 0x000000010c41e5c4 StreamChat`merged generic specialization <StreamChat.AttachmentDTO, StreamChat.AttachmentDTO> of closure #1 (Swift.Array<StreamChat.ListChange<τ_0_0>>) -> () in StreamChat.ListDatabaseObserver.onChange.didset : Swift.Optional<(Swift.Array<StreamChat.ListChange<τ_0_0>>) -> ()> + 100
frame #8: 0x000000010c5762c4 StreamChat`specialized ListChangeAggregator.controllerDidChangeContent(self=<unavailable>) at ListDatabaseObserver.swift:362:20 [opt]
frame #9: 0x000000010c5755b0 StreamChat`@objc ListChangeAggregator.controllerDidChangeContent(_:) [inlined] StreamChat.ListChangeAggregator.controllerDidChangeContent(__C.NSFetchedResultsController<__C.NSFetchRequestResult>) -> () at <compiler-generated>:0 [opt]
frame #10: 0x000000010c5755ac StreamChat`@objc ListChangeAggregator.controllerDidChangeContent(_:) at <compiler-generated>:361:10 [opt]
frame #11: 0x000000012bf7dd58 CoreData`__82-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:]_block_invoke + 6576
frame #12: 0x000000012bf11098 CoreData`developerSubmittedBlockToNSManagedObjectContextPerform + 156
frame #13: 0x000000012bf10f6c CoreData`-[NSManagedObjectContext performBlockAndWait:] + 216
frame #14: 0x000000012bf7c38c CoreData`-[NSFetchedResultsController _core_managedObjectContextDidChange:] + 112
frame #15: 0x00000001181c6f90 CoreFoundation`__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20
frame #16: 0x00000001181c6f48 CoreFoundation`___CFXRegistrationPost_block_invoke + 48
frame #17: 0x00000001181c6358 CoreFoundation`_CFXRegistrationPost + 416
frame #18: 0x00000001181c5d48 CoreFoundation`_CFXNotificationPost + 692
frame #19: 0x000000010701d964 Foundation`-[NSNotificationCenter postNotificationName:object:userInfo:] + 92
frame #20: 0x000000012bf178e0 CoreData`-[NSManagedObjectContext _createAndPostChangeNotification:deletions:updates:refreshes:deferrals:wasMerge:] + 2284
frame #21: 0x000000012bf18034 CoreData`-[NSManagedObjectContext _postRefreshedObjectsNotificationAndClearList] + 196
frame #22: 0x000000012bf03294 CoreData`-[NSManagedObjectContext _processRecentChanges:] + 104
frame #23: 0x000000012bf107f0 CoreData`-[NSManagedObjectContext _mergeChangesFromDidSaveDictionary:usingObjectIDs:] + 4460
frame #24: 0x000000012bf10afc CoreData`-[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 468
frame #25: 0x000000012bf11098 CoreData`developerSubmittedBlockToNSManagedObjectContextPerform + 156
frame #26: 0x0000000117db9b94 libdispatch.dylib`_dispatch_client_callout + 16
frame #27: 0x0000000117dc8650 libdispatch.dylib`_dispatch_main_queue_drain + 1064
frame #28: 0x0000000117dc8218 libdispatch.dylib`_dispatch_main_queue_callback_4CF + 40
frame #29: 0x00000001181f5c2c CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
frame #30: 0x00000001181f00b0 CoreFoundation`__CFRunLoopRun + 2432
frame #31: 0x00000001181ef218 CoreFoundation`CFRunLoopRunSpecific + 572
frame #32: 0x000000011fee760c GraphicsServices`GSEventRunModal + 160
frame #33: 0x000000012f7fda98 UIKitCore`-[UIApplication _run] + 992
frame #34: 0x000000012f802634 UIKitCore`UIApplicationMain + 112
frame #35: 0x0000000102474bec *****`main at AppDelegate.swift:25:7
frame #36: 0x0000000102d41cd8 dyld_sim`start_sim + 20
frame #37: 0x0000000102a8908c dyld`start + 520
Thread 11
* thread #11, queue = 'rxswift.queue.DispatchQoS(qosClass: Dispatch.DispatchQoS.QoSClass.userInteractive, relativePriority: 0)'
* frame #0: 0x0000000118072dd4 libsystem_kernel.dylib`__ulock_wait + 8
frame #1: 0x0000000117dba5fc libdispatch.dylib`_dlock_wait + 52
frame #2: 0x0000000117dba3ac libdispatch.dylib`_dispatch_thread_event_wait_slow + 52
frame #3: 0x0000000117dc997c libdispatch.dylib`__DISPATCH_WAIT_FOR_QUEUE__ + 368
frame #4: 0x0000000117dc9330 libdispatch.dylib`_dispatch_sync_f_slow + 192
frame #5: 0x000000012bf10f9c CoreData`-[NSManagedObjectContext performBlockAndWait:] + 264
frame #6: 0x000000010c4231a4 StreamChat`specialized closure #1 in closure #1 in ListDatabaseObserver.startObserving(dto=0x000060000163d590, context=<unavailable>, itemCreator=0x0000000000000000) at ListDatabaseObserver.swift:188:25 [opt]
frame #7: 0x000000010c689ab8 StreamChat`merged generic not re-abstracted specialization <Swift.Optional<StreamChat.ChatMessage>, Swift.Array<StreamChat.MessageDTO>, StreamChat.MessageDTO> of closure #1 (Swift.Int) -> τ_0_0 in StreamChat.LazyCachedMapCollection.init<τ_0_0, τ_0_1 where τ_1_0: Swift.RandomAccessCollection, τ_1_1 == τ_1_0.Element, τ_1_0.Index == Swift.Int>(source: τ_1_0, map: (τ_1_1) -> τ_0_0) -> StreamChat.LazyCachedMapCollection<τ_0_0> + 116
frame #8: 0x000000010c68d820 StreamChat`partial apply for specialized closure #1 in LazyCachedMapCollection.init<A, B>(source:map:) at <compiler-generated>:0 [opt]
frame #9: 0x000000010c41bd78 StreamChat`specialized Sequence.compactMap<A>(_:) at LazyCachedMapCollection.swift:51:25 [opt]
frame #10: 0x000000010c41bcf4 StreamChat`specialized Sequence.compactMap<A>(_:) [inlined] generic specialization <Swift.Optional<StreamChat.ChatChannel>> of StreamChat.LazyCachedMapCollection.subscript.read : (position=9, self=StreamChat.LazyCachedMapCollection<Swift.Optional<StreamChat.ChatChannel>> @ 0x000060000adf53c0) -> τ_0_0 at LazyCachedMapCollection.swift:0 [opt]
frame #11: 0x000000010c41bcf4 StreamChat`specialized Sequence.compactMap<A>(_:) [inlined] generic specialization <Swift.Optional<StreamChat.ChatChannel>> of protocol witness for Swift.Collection.subscript.read : (τ_0_0.Index) -> τ_0_0.Element in conformance StreamChat.LazyCachedMapCollection<τ_0_0> : Swift.Collection in StreamChat at <compiler-generated>:47:12 [opt]
frame #12: 0x000000010c41bcf4 StreamChat`specialized Sequence.compactMap<A>(_:) [inlined] generic specialization <StreamChat.LazyCachedMapCollection<Swift.Optional<StreamChat.ChatChannel>>> of Swift.IndexingIterator.next() -> Swift.Optional<τ_0_0.Element> at <compiler-generated>:0 [opt]
frame #13: 0x000000010c41bcc0 StreamChat`specialized Sequence.compactMap<A>(_:) [inlined] generic specialization <StreamChat.LazyCachedMapCollection<Swift.Optional<StreamChat.ChatChannel>>> of protocol witness for Swift.IteratorProtocol.next() -> Swift.Optional<τ_0_0.Element> in conformance Swift.IndexingIterator<τ_0_0> : Swift.IteratorProtocol in Swift at <compiler-generated>:0 [opt]
frame #14: 0x000000010c41bcc0 StreamChat`specialized Sequence.compactMap<A>(_:) at <compiler-generated>:0 [opt]
frame #15: 0x000000010c420f34 StreamChat`specialized closure #1 in ListDatabaseObserver.startObserving() [inlined] generic specialization <Swift.Array<StreamChat.ChannelDTO>, Swift.Optional<StreamChat.ChatChannel>> of Swift.RandomAccessCollection< where τ_0_0.Index == Swift.Int>.lazyCachedMap<τ_0_0>(transformation=0x0000000000000000, self=<unavailable>) -> τ_1_0) -> StreamChat.LazyCachedMapCollection<τ_1_0> at ListDatabaseObserver.swift:197:41 [opt]
frame #16: 0x000000010c420f20 StreamChat`specialized closure #1 in ListDatabaseObserver.startObserving(self=<unavailable>) at ListDatabaseObserver.swift:186:49 [opt]
frame #17: 0x000000010c434130 StreamChat`partial apply for specialized thunk for @escaping @callee_guaranteed () -> (@owned LazyCachedMapCollection<A>) [inlined] generic specialization <StreamChat.ChatChannelMember, StreamChat.MemberDTO> of reabstraction thunk helper <τ_0_0, τ_0_1 where τ_0_1: __C.NSManagedObject> from @escaping @callee_guaranteed () -> (@owned StreamChat.LazyCachedMapCollection<τ_0_0>) to @escaping @callee_guaranteed () -> (@out StreamChat.LazyCachedMapCollection<τ_0_0>) at <compiler-generated>:0 [opt]
frame #18: 0x000000010c43412c StreamChat`partial apply for specialized thunk for @escaping @callee_guaranteed () -> (@owned LazyCachedMapCollection<A>) [inlined] generic not re-abstracted specialization <StreamChat.ChatChannelMember, StreamChat.MemberDTO> of reabstraction thunk helper <τ_0_0, τ_0_1 where τ_0_1: __C.NSManagedObject> from @escaping @callee_guaranteed () -> (@owned StreamChat.LazyCachedMapCollection<τ_0_0>) to @escaping @callee_guaranteed () -> (@out StreamChat.LazyCachedMapCollection<τ_0_0>) at <compiler-generated>:0 [opt]
frame #19: 0x000000010c43412c StreamChat`partial apply for specialized thunk for @escaping @callee_guaranteed () -> (@owned LazyCachedMapCollection<A>) at <compiler-generated>:0 [opt]
frame #20: 0x000000010c434888 StreamChat`partial apply forwarder for generic not re-abstracted specialization <StreamChat.ChatChannel, StreamChat.ChannelDTO> of reabstraction thunk helper <τ_0_0, τ_0_1 where τ_0_1: __C.NSManagedObject> from @escaping @callee_guaranteed () -> (@owned StreamChat.LazyCachedMapCollection<τ_0_0>) to @escaping @callee_guaranteed () -> (@out StreamChat.LazyCachedMapCollection<τ_0_0>) + 12
frame #21: 0x000000010c60ef9c StreamChat`merged generic specialization <StreamChat.LazyCachedMapCollection<StreamChat.ChatMessage>> of closure #1 (inout Swift.Optional<τ_0_0>) -> () in StreamChat.Cached.wrappedValue.getter : τ_0_0 + 268
frame #22: 0x000000010c41e41c StreamChat`merged generic specialization <StreamChat.LazyCachedMapCollection<StreamChat.AttachmentDTO>> of StreamChat.Cached.wrappedValue.getter : τ_0_0 at Cached.swift:0
frame #23: 0x000000010c4b018c StreamChat`ChatChannelListController.loadNextChannels(limit:completion:) [inlined] generic specialization <StreamChat.ChatChannel, StreamChat.ChannelDTO> of StreamChat.ListDatabaseObserver.items.getter : StreamChat.LazyCachedMapCollection<τ_0_0>(self=0x00006000018a6000) at <compiler-generated>:0 [opt]
frame #24: 0x000000010c4b016c StreamChat`ChatChannelListController.loadNextChannels(limit:completion:) [inlined] StreamChat.ChatChannelListController.channels.getter : StreamChat.LazyCachedMapCollection<StreamChat.ChatChannel>(self=0x000000029a24dbd0) at ChannelListController.swift:48:36 [opt]
frame #25: 0x000000010c4b014c StreamChat`ChatChannelListController.loadNextChannels(limit=<unavailable>, completion=0x00000001147d855c Messenger`partial apply forwarder for closure #1 (Swift.Optional<Swift.Error>) -> () in closure #1 (RxSwift.AnyObserver<StreamChat.LazyCachedMapCollection<StreamChat.ChatChannel>>) -> RxSwift.Disposable in Messenger.StreamChatLibrary.performChannelsRequest(with: StreamChat.ChatChannelListController) -> RxSwift.Observable<StreamChat.LazyCachedMapCollection<StreamChat.ChatChannel>> at <compiler-generated>, self=0x000000029a24dbd0) at ChannelListController.swift:322:71 [opt]
frame #26: 0x00000001147d467c Messenger`closure #1 in StreamChatLibrary.performChannelsRequest(observer=(observer = 0x000000010b07322c RxSwift`partial apply forwarder for implicit closure #2 (RxSwift.Event<A>) -> () in implicit closure #1 (A1) -> (RxSwift.Event<A>) -> () in RxSwift.AnyObserver.init<A where A == A1.Element, A1: RxSwift.ObserverType>(A1) -> RxSwift.AnyObserver<A> at <compiler-generated>), controller=0x000000029a24dbd0) at StreamChatLibrary+Channel.swift:196:24
frame #27: 0x000000010b09b264 RxSwift`AnonymousObservable.run<A>(_:cancel:) [inlined] RxSwift.AnonymousObservableSink.run(parent=<unavailable>, self=<unavailable>) -> RxSwift.Disposable at Create.swift:60:16 [opt]
frame #28: 0x000000010b09b218 RxSwift`AnonymousObservable.run<A>(observer=<unavailable>, cancel=<unavailable>, self=<unavailable>) at Create.swift:75:33 [opt]
frame #29: 0x000000010b0d2744 RxSwift`Producer.subscribe<Element>(observer=0x00006000018f3480, self=0x000060000309c8a0) at Producer.swift:18:44 [opt]
frame #30: 0x000000010b0bf970 RxSwift`MergeSink.run(source=0x000060000309c8a0, self=<unavailable>) at Merge.swift:509:35 [opt]
frame #31: 0x000000010b0c0894 RxSwift`merged RxSwift.FlatMap.run<τ_0_0 where τ_1_0: RxSwift.ObserverType, τ_0_1.Element == τ_1_0.Element>(_: τ_1_0, cancel: RxSwift.Cancelable) -> (sink: RxSwift.Disposable, subscription: RxSwift.Disposable) + 268
frame #32: 0x000000010b0c073c RxSwift`RxSwift.FlatMap.run<τ_0_0 where τ_1_0: RxSwift.ObserverType, τ_0_1.Element == τ_1_0.Element>(_: τ_1_0, cancel: RxSwift.Cancelable) -> (sink: RxSwift.Disposable, subscription: RxSwift.Disposable) + 52
frame #33: 0x000000010b0d2744 RxSwift`Producer.subscribe<Element>(observer=0x00006000001144d0, self=0x0000600003b48b10) at Producer.swift:18:44 [opt]
frame #34: 0x000000010b0c8e9c RxSwift`ObserveOn.run<A>(observer=<unavailable>, cancel=<unavailable>, self=<unavailable>) at ObserveOn.swift:64:40 [opt]
frame #35: 0x000000010b0d2744 RxSwift`Producer.subscribe<Element>(observer=0x00006000012fdf20, self=0x0000600002d7c8c0) at Producer.swift:18:44 [opt]
frame #36: 0x000000010b07e2ec RxSwift`CatchSink.run(self=<unavailable>) at Catch.swift:163:45 [opt]
frame #37: 0x000000010b07e7b4 RxSwift`Catch.run<A>(observer=<unavailable>, cancel=<unavailable>, self=<unavailable>) at Catch.swift:204:33 [opt]
frame #38: 0x000000010b0d2744 RxSwift`Producer.subscribe<Element>(observer=0x00006000012fefa0, self=0x0000600003b48ab0) at Producer.swift:18:44 [opt]
frame #39: 0x000000010b0fdbf8 RxSwift`ToArray.run<SourceType>(observer=<unavailable>, cancel=<unavailable>, self=<unavailable>) at ToArray.swift:61:40 [opt]
frame #40: 0x000000010b0d2744 RxSwift`Producer.subscribe<Element>(observer=0x00006000012fd7a0, self=0x000060000309c0c0) at Producer.swift:18:44 [opt]
frame #41: 0x000000010b0927c4 RxSwift`CompactMap.run<SourceType>(observer=<unavailable>, cancel=<unavailable>, self=<unavailable>) at CompactMap.swift:73:40 [opt]
frame #42: 0x000000010b0d2744 RxSwift`Producer.subscribe<Element>(observer=0x000060000042d440, self=0x0000600003b48cf0) at Producer.swift:18:44 [opt]
frame #43: 0x000000010b0f2248 RxSwift`SwitchSink.run(source=0x0000600003b48cf0, self=<unavailable>) at Switch.swift:83:35 [opt]
frame #44: 0x000000010b0f32fc RxSwift`FlatMapLatest.run<SourceType>(observer=<unavailable>, cancel=<unavailable>, self=<unavailable>) at Switch.swift:248:33 [opt]
frame #45: 0x000000010b0d3578 RxSwift`closure #1 in Producer.subscribe<A>(self=0x0000600003b482a0, observer=<unavailable>) at Producer.swift:26:48 [opt]
frame #46: 0x000000010b0d2998 RxSwift`specialized CurrentThreadScheduler.schedule<A>(state=() @ scalar, action=0x000000010b0d363c RxSwift`partial apply forwarder for closure #1 (()) -> RxSwift.Disposable in RxSwift.Producer.subscribe<A where A == A1.Element, A1: RxSwift.ObserverType>(A1) -> RxSwift.Disposable at <compiler-generated>, self=<unavailable>) at CurrentThreadScheduler.swift:94:30 [opt]
frame #47: 0x000000010b0d281c RxSwift`Producer.subscribe<Element>(observer=<unavailable>, self=<unavailable>) at Producer.swift:24:52 [opt]
frame #48: 0x000000010b0c57b4 RxSwift`protocol witness for ObservableType.subscribe<A>(_:) in conformance Observable<A> at <compiler-generated>:0 [opt]
frame #49: 0x000000010b0f1040 RxSwift`closure #1 in SubscribeOnSink.run(self=<unavailable>, disposeEverything=0x000060000166cc80) at SubscribeOn.swift:78:51 [opt]
frame #50: 0x000000010b0a642c RxSwift`partial apply for closure #1 in DispatchQueueConfiguration.schedule<A>(_:action:) [inlined] closure #1 (cancel=0x0000600002d7c900, action=0x0000000000000000, state=<unavailable>) -> () in RxSwift.DispatchQueueConfiguration.schedule<τ_0_0>(_: τ_0_0, action: (τ_0_0) -> RxSwift.Disposable) -> RxSwift.Disposable at DispatchQueueConfiguration.swift:27:34 [opt]
frame #51: 0x000000010b0a6420 RxSwift`partial apply for closure #1 in DispatchQueueConfiguration.schedule<A>(_:action:) at <compiler-generated>:0 [opt]
frame #52: 0x000000010b0a5f4c RxSwift`thunk for @escaping @callee_guaranteed () -> () at <compiler-generated>:0 [opt]
frame #53: 0x0000000117db833c libdispatch.dylib`_dispatch_call_block_and_release + 24
frame #54: 0x0000000117db9b94 libdispatch.dylib`_dispatch_client_callout + 16
frame #55: 0x0000000117dbc89c libdispatch.dylib`_dispatch_continuation_pop + 556
frame #56: 0x0000000117dbbd00 libdispatch.dylib`_dispatch_async_redirect_invoke + 696
frame #57: 0x0000000117dcbfec libdispatch.dylib`_dispatch_root_queue_drain + 440
frame #58: 0x0000000117dccab8 libdispatch.dylib`_dispatch_worker_thread2 + 188
frame #59: 0x0000000118113b04 libsystem_pthread.dylib`_pthread_wqthread + 224
@Aurazion, does this happen every time? It is 100% reproducible? 🤔
On my side yes with every opening of the app, no freeze with 4.19 SDK 🤷♂️ This stacktrace is from a simulator (iPhone 13 Pro Max, iOS 15.5) with Xcode 13.4.1 (13F100)
Many of our TestFlight users contact us to report an app crash/freeze on launch. And this happened right after SDK update to 4.20 in our latest release.
@Aurazion in order for us to identify the issue, can you please try and point the SDK to this commit: bc329b328134c97156f9b63371585b1a5f8f7bd7
, and see if the issue is gone?
Thank you!
Still have the same issue, even after deleting the app. 😅
Still have the same issue, even after deleting the app. 😅
Even pointing to that commit as well?
Yes, with the reverted modifications
@Aurazion, which dependency manager are you using? Please make sure that there is no caching happening.
Can you also provide a snippet of your channel list implementation? Since we can't reproduce this in our Demo App, maybe with your setup we can reproduce it and it will be easier to pinpoint the problem.
Best, Nuno
Hi @nuno-vieira, we use Cocoapods and yes I'm sure the cache was cleaned before. Could we plan a call together to talk about it ?
Thanks
Hi @AndrewSB, so I did a call with @Aurazion, and we were able to work around it for now. This is a deadlock issue and it is quite hard to pinpoint it, so we will need more time to investigate it especially because it is not obvious what 4.20.0 could have introduced to cause this.
Either way, if you are calling synchronise()
or accessing controllers from background threads, changing to the main thread it will fix the issue. Ofc, if this is possible and it doesn't cause performance issues on your side.
Let us know if this is possible for now.
Best, Nuno
we'll check out if we're calling synchronize off the main thread, thanks for continuing to improve this 🙃
@AndrewSB @Aurazion
Update: Actually, we were able to reproduce this issue on our end. And it was indeed an issue introduced on 4.20.0. We are currently working on it and we should have a fix ready soon :)
@AndrewSB The issue is actually not calling synchronise from a background thread, but calling controller properties from a background thread. Example: channelListController.channels
-> calling this from a background thread will deadlock on 4.20.0.
Best, Nuno
got it, is the controller not thread safe? are we not supposed to call it off the main thread?
would we be able to downgrade to a previous version, and then once your fix is in (4.20.1), continue to call controller properties off the main thread?
@AndrewSB Yes, better to downgrade to 4.20.0.
It is thread-safe, but because of a change in our internal ListDatabaseObserver, it created a deadlock when accessing it from a different thread. But you can use controllers from a different thread without a problem. This is a 4.20.0 issue only.
Hi!
This issue is now solved in the 4.21.1 release.
Thank you for your patience!
Best, Nuno
one more crash for you martin
looks like lock crashes? this might need to be inside stream-chat-swift, not the SwiftUI code