Skip to content

Fix reactions modal crash when no reactions can be displayed#6475

Merged
andremion merged 1 commit into
v6from
fix/user-reactions-empty-span-count
May 27, 2026
Merged

Fix reactions modal crash when no reactions can be displayed#6475
andremion merged 1 commit into
v6from
fix/user-reactions-empty-span-count

Conversation

@andremion
Copy link
Copy Markdown
Contributor

@andremion andremion commented May 27, 2026

Closes AND-1194

Goal

Fix the IllegalArgumentException: Span count should be at least 1. Provided 0 crash from UserReactionsView.bindReactionList when the reactions modal opens on a message whose filtered latestReactions ends up empty.

Implementation

UserReactionsView.bindReactionList set gridLayoutManager.spanCount directly from the size of the filtered reaction list:

gridLayoutManager.spanCount = userReactionItems.size.coerceAtMost(MAX_COLUMNS_COUNT)

When userReactionItems is empty — every reaction has user == null, or ChatUI.supportedReactions.getReactionDrawable(type) == null, or latestReactions itself is empty while reactionGroups is populated — spanCount = 0 is passed to GridLayoutManager.setSpanCount, which rejects it.

Clamp the value to at least 1:

gridLayoutManager.spanCount = userReactionItems.size
    .coerceAtMost(MAX_COLUMNS_COUNT)
    .coerceAtLeast(1)

spanCount = 1 on an empty RecyclerView is harmless — the grid has no rows regardless of the span count. The modal opens with its title ("0 reactions") and an empty grid instead of crashing.

./gradlew apiDump produced zero .api diff, confirming no public surface change.

Testing

Manual repro needs a small sample-app patch — applied to ComponentBrowserUserReactionsFragment and its layout — that adds a tap target which calls UserReactionsView.setMessage with latestReactions = emptyList(). Apply the patch below, then:

  1. Run stream-chat-android-ui-components-sample. On the user picker, tap the SDK Version label at the bottom to open the Component Browser.
  2. Open UserReactionsView.
  3. Below the four demo cards, tap the "Tap to repro IllegalArgumentException crash (empty latestReactions)" label.
  • Before this fix: crash at UserReactionsView.kt:103 with the exact stack trace reported by the customer.
  • After this fix: the modal opens with an empty grid, no crash.

Also verified:

  • ./gradlew spotlessApply detekt apiDump — clean.
  • ./gradlew :stream-chat-android-ui-components:testDebugUnitTest — green.
Sample-app patch for manual verification
diff --git a/stream-chat-android-ui-components-sample/src/main/kotlin/io/getstream/chat/ui/sample/feature/componentbrowser/reactions/ComponentBrowserUserReactionsFragment.kt b/stream-chat-android-ui-components-sample/src/main/kotlin/io/getstream/chat/ui/sample/feature/componentbrowser/reactions/ComponentBrowserUserReactionsFragment.kt
index 9bb0c01416..dc4bcde396 100644
--- a/stream-chat-android-ui-components-sample/src/main/kotlin/io/getstream/chat/ui/sample/feature/componentbrowser/reactions/ComponentBrowserUserReactionsFragment.kt
+++ b/stream-chat-android-ui-components-sample/src/main/kotlin/io/getstream/chat/ui/sample/feature/componentbrowser/reactions/ComponentBrowserUserReactionsFragment.kt
@@ -23,6 +23,7 @@ import android.view.ViewGroup
 import androidx.fragment.app.Fragment
 import io.getstream.chat.android.core.internal.InternalStreamChatApi
 import io.getstream.chat.android.models.Reaction
+import io.getstream.chat.android.models.User
 import io.getstream.chat.android.ui.helper.SupportedReactions.DefaultReactionTypes.LOL
 import io.getstream.chat.android.ui.helper.SupportedReactions.DefaultReactionTypes.LOVE
 import io.getstream.chat.android.ui.helper.SupportedReactions.DefaultReactionTypes.THUMBS_DOWN
@@ -104,6 +105,22 @@ class ComponentBrowserUserReactionsFragment : Fragment() {
                 ),
                 currentUser = currentUser,
             )
+            setupEmptyReactionsCrashRepro(currentUser)
+        }
+    }
+
+    /**
+     * Repro for `IllegalArgumentException("Span count should be at least 1. Provided 0")`
+     * thrown from `UserReactionsView.bindReactionList` (line 103). Triggered when a message
+     * displays a reactions bubble but its `latestReactions` list contains no entries that
+     * survive the supported-reactions / non-null user / non-null drawable filter.
+     */
+    private fun setupEmptyReactionsCrashRepro(currentUser: User) {
+        binding.crashReproLabel.setOnClickListener {
+            binding.userReactionsView5.setMessage(
+                message = randomMessage().copy(latestReactions = mutableListOf()),
+                currentUser = currentUser,
+            )
         }
     }
 }
diff --git a/stream-chat-android-ui-components-sample/src/main/res/layout/fragment_component_browser_user_reactions_view.xml b/stream-chat-android-ui-components-sample/src/main/res/layout/fragment_component_browser_user_reactions_view.xml
index 6f4b2e31be..5299a47ade 100644
--- a/stream-chat-android-ui-components-sample/src/main/res/layout/fragment_component_browser_user_reactions_view.xml
+++ b/stream-chat-android-ui-components-sample/src/main/res/layout/fragment_component_browser_user_reactions_view.xml
@@ -79,6 +79,26 @@
                 android:layout_marginTop="8dp"
                 />
 
+            <TextView
+                android:id="@+id/crashReproLabel"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="24dp"
+                android:padding="12dp"
+                android:background="?attr/selectableItemBackground"
+                android:textColor="@color/stream_ui_text_color_primary"
+                android:textStyle="bold"
+                android:gravity="center"
+                android:text="Tap to repro IllegalArgumentException crash (empty latestReactions)"
+                />
+
+            <io.getstream.chat.android.ui.feature.messages.list.reactions.user.internal.UserReactionsView
+                android:id="@+id/userReactionsView5"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="8dp"
+                />
+
         </LinearLayout>
 
     </ScrollView>

Summary by CodeRabbit

  • Bug Fixes
    • Improved the reaction grid layout calculation to correctly handle all display scenarios. The grid now enforces appropriate column span bounds with both minimum and maximum limits, resolving visual rendering issues that occurred with empty reaction lists. This ensures consistent and reliable presentation regardless of the number of reactions displayed.

Review Change Stack

…list crash

UserReactionsView.bindReactionList set GridLayoutManager.spanCount directly
from the size of the filtered reaction list. When the filter produces an
empty list (e.g. reactions whose user is null, or whose type has no
registered drawable in ChatUI.supportedReactions), spanCount = 0 was passed
to GridLayoutManager.setSpanCount, which rejects it with
IllegalArgumentException("Span count should be at least 1. Provided 0").

Coerce the value to at least 1. spanCount = 1 on an empty RecyclerView is
harmless; the modal opens with an empty grid instead of crashing.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

PR checklist ✅

All required conditions are satisfied:

  • Title length is OK (or ignored by label).
  • At least one pr: label exists.
  • Sections ### Goal, ### Implementation, and ### Testing are filled (or ignored for dependabot PRs).

🎉 Great job! This PR is ready for review.

@andremion andremion added the pr:bug Bug fix label May 27, 2026
@andremion
Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 27, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 27, 2026

Walkthrough

This PR fixes a layout edge case in the user reactions view by enforcing valid grid span count boundaries. The reaction grid's layout manager now clamps column count to a minimum of 1 and maximum of MAX_COLUMNS_COUNT, preventing invalid state when no reactions are displayed.

Changes

User Reactions Grid Layout

Layer / File(s) Summary
Span count bounds enforcement
stream-chat-android-ui-components/src/main/kotlin/io/getstream/chat/android/ui/feature/messages/list/reactions/user/internal/UserReactionsView.kt
Grid layout span count is clamped to enforce a minimum of 1 and maximum of MAX_COLUMNS_COUNT, fixing invalid span calculations when the reaction item list is empty.

🎯 1 (Trivial) | ⏱️ ~3 minutes

🐰 A grid that's not quite right,
With columns gone out of sight,
One bounded below, MAX above too,
Now reactions display just right, it's true!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description comprehensively covers Goal, Implementation with code examples, detailed Testing instructions with a manual repro patch, and verification of checks. It aligns well with the template structure.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately describes the main change: preventing a crash in UserReactionsView when displaying an empty reactions list.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/user-reactions-empty-span-count

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

SDK Size Comparison 📏

SDK Before After Difference Status
stream-chat-android-client 5.26 MB 5.29 MB 0.03 MB 🟢
stream-chat-android-offline 5.49 MB 5.50 MB 0.01 MB 🟢
stream-chat-android-ui-components 10.64 MB 10.70 MB 0.06 MB 🟢
stream-chat-android-compose 12.87 MB 12.89 MB 0.03 MB 🟢

@sonarqubecloud
Copy link
Copy Markdown

@andremion andremion changed the title fix(ui-components): prevent UserReactionsView empty-list crash Fix reactions modal crash when no reactions can be displayed May 27, 2026
@andremion andremion marked this pull request as ready for review May 27, 2026 10:20
@andremion andremion requested a review from a team as a code owner May 27, 2026 10:20
@andremion andremion merged commit 747d826 into v6 May 27, 2026
18 of 19 checks passed
@andremion andremion deleted the fix/user-reactions-empty-span-count branch May 27, 2026 10:26
@stream-public-bot stream-public-bot added the released Included in a release label May 28, 2026
@stream-public-bot
Copy link
Copy Markdown
Contributor

🚀 Available in v6.39.0

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

Labels

pr:bug Bug fix released Included in a release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants