fayharinn
### Description `performScrollTo` crashes with `NSInternalInconsistencyException` when a scroll to the oldest message is requested while the table has no sections. `Sources/ExyteChat/Views/UIList.swift` (current `main`, unchanged since at least 3.1.7): ```swift case .oldestMessage: let lastSection = max(tableView.numberOfSections - 1, 0) let lastRow = max(tableView.numberOfRows(inSection: lastSection) - 1, 0) guard lastRow >= 0 else { return } … ``` With zero sections, `max(0 - 1, 0)` evaluates to `0`, so the next line asks UIKit for the row count of a section that does not exist: ``` NSInternalInconsistencyException: Requested the number of rows for section (0) which is out of bounds. -[UITableViewRowData numberOfRowsInSection:] ``` The `guard lastRow >= 0` cannot help: `max(_, 0)` already forced the value non-negative, so the guard is always true, and it runs after the offending call regardless. ### Why this is reachable in normal use `ChatView.swift` arms this scroll from a status bar tap: ```swift .onStatusBarTap { self.pendingScrollTo = ScrollToParams(.oldestMessage) } ``` `View+StatusBar.swift` implements that by swizzling `UIStatusBarManager.handleTapAction:` and posting a **global** `NotificationCenter` notification. The subscription is created in `onAppear` and released in `onDisappear`. `onDisappear` does not fire for a view that stays mounted while off screen, which is the normal case for a `ChatView` inside a `TabView` tab or lower in a `NavigationStack`. The observer therefore survives navigation, and a status bar tap performed on a completely different screen still arms the scroll on that chat. If its table is empty at that moment (empty conversation, or messages not loaded yet), the app crashes. The scroll runs inside `UIView.animate` wrapped in `withCheckedContinuation` (`UIList.swift:128`), so the exception surfaces from inside the animation block: ``` -[UITableViewRowData numberOfRowsInSection:] … +[UIView(UIViewAnimationWithBlocks) animateWithDuration:animations:completion:] closure in withCheckedContinuation<T> withCheckedContinuation<T> ``` ### Steps to reproduce 1. Present a `ChatView` for a conversation with no messages, or one whose messages load asynchronously. 2. Navigate away while keeping the view mounted (switch tab, or push another screen onto the stack). 3. Tap the status bar. Observed on iOS 27.0, iPhone 13 Pro, ExyteChat 3.1.7. The same code path is present on `main` and in 3.2.7. ### Suggested fix Guard on the section count before touching the table, and drop both clamps so the row guard becomes meaningful for an empty section: ```swift case .oldestMessage: guard tableView.numberOfSections > 0 else { return } let lastSection = tableView.numberOfSections - 1 let lastRow = tableView.numberOfRows(inSection: lastSection) - 1 guard lastRow >= 0 else { return } ``` Happy to open a PR with this.