Skip to content

Fix crash when scrolling to oldest message on an empty table - #292

Merged
f3dm76 merged 1 commit into
exyte:mainfrom
fayharinn:fix/scroll-to-oldest-on-empty-table
Aug 14, 2026
Merged

f3dm76 merged 1 commit into
exyte:mainfrom
fayharinn:fix/scroll-to-oldest-on-empty-table

Conversation

@fayharinn

Copy link
Copy Markdown
Contributor

Fixes #291.

performScrollTo's .oldestMessage branch clamps the section index with max(numberOfSections - 1, 0), so an empty table still asks UIKit for section 0:

NSInternalInconsistencyException: Requested the number of rows for section (0) which is out of bounds.
-[UITableViewRowData numberOfRowsInSection:]

The existing guard lastRow >= 0 never fires, because max(_, 0) already forced the value non-negative, and it runs after the offending call anyway.

This guards on the section count first, then drops both clamps so the row guard becomes meaningful for an empty section. No behaviour change on a populated table.

The path is reachable in normal use: onStatusBarTap arms pendingScrollTo = .oldestMessage, and that subscription is a global NotificationCenter observer released in onDisappear, which does not fire while a ChatView stays mounted off screen (a TabView tab, or lower in a NavigationStack). A status bar tap from another screen then scrolls a chat whose table is still empty. Issue #291 has the full trace and reproduction steps.

Observed on iOS 27.0 with 3.1.7; the same code is on main and in 3.2.7.

performScrollTo's .oldestMessage branch clamps the section index with
max(numberOfSections - 1, 0), so an empty table still asks UIKit for
section 0:

    Requested the number of rows for section (0) which is out of bounds.

The existing `guard lastRow >= 0` never fires, because max(_, 0) already
forced it non-negative, and it runs after the offending call anyway.

Guard on the section count first, then drop both clamps so the row guard
becomes meaningful for an empty section.

This is reachable in normal use: onStatusBarTap sets
pendingScrollTo = .oldestMessage, and the subscription is a global
NotificationCenter observer torn down in onDisappear, which does not fire
while a ChatView stays mounted off screen (a TabView tab, or lower in a
NavigationStack). A status bar tap from another screen then scrolls a chat
whose table is still empty, and the app crashes.
@fayharinn
fayharinn force-pushed the fix/scroll-to-oldest-on-empty-table branch from 3d1aeb5 to f9ecf93 Compare August 14, 2026 07:39
@f3dm76
f3dm76 merged commit e3a9986 into exyte:main Aug 14, 2026
@f3dm76

f3dm76 commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Hey @fayharinn, thank you so much for the fix, have a brilliant day!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash: scroll to oldest message on an empty table raises NSInternalInconsistencyException

2 participants