Repository navigation
Crash when using SliverGrid, findChildIndexCallback, a sparsely populated grid and updating the children #138749
Copy link
Copy link
Closed
Labels
P0Critical issues such as a build break or regressionCritical issues such as a build break or regressiona: error messageError messages from the Flutter frameworkError messages from the Flutter frameworkf: scrollingViewports, list views, slivers, etc.Viewports, list views, slivers, etc.found in release: 3.16Found to occur in 3.16Found to occur in 3.16found in release: 3.17Found to occur in 3.17Found to occur in 3.17frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
Description
Is there an existing issue for this?
- I have searched the existing issues
- I have read the guide to filing a bug
Steps to reproduce
In the app I'm working on, we have a custom SliverGrid layout. It does a somewhat sparse layout of grid items, with a contiguous series of items and other items interspersed along the way. Some actions performed in the app causes the grid contents to be limited - thus items are removed from the grid.
We also use a findChildIndexCallback with SliverChildBuilderDelegate. It seems like that combination can lead to places in the grid where removing items leads to a crash.
- Open https://dartpad.dev/?id=d9f723468f22d4035dfcf90366802151
- Run app
- Scroll down until "grid item 7" just scrolls into view in the left column
- Press the FAB/refresh button in the bottom right
Expected results
No crashes or issues.
Actual results
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
The following assertion was thrown during performLayout():
Assertion failed:
file:///opt/flutter/packages/flutter/lib/src/rendering/sliver_multi_box_adaptor.dart:508:12
childCount >= leadingGarbage + trailingGarbage
is not true
Widget creation tracking is currently disabled. Enabling it enables improved error messages. It can
be enabled by passing `--track-widget-creation` to `flutter run` or `flutter test`.
When the exception was thrown, this was the stack
The following RenderObject was being processed when the exception was fired: RenderSliverGrid#255ad relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE:
needs compositing
creator: SliverGrid ← Viewport ← IgnorePointer-[GlobalKey#e6cb3] ← Semantics ← Listener ←
_GestureSemantics ← RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#04dfe] ←
Listener ← _ScrollableScope ← _ScrollSemantics-[GlobalKey#8e450] ←
NotificationListener<ScrollMetricsNotification> ← RepaintBoundary ← ⋯
parentData: paintOffset=Offset(0.0, 0.0) (can use size)
constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.idle,
scrollOffset: 6878.2, remainingPaintExtent: 805.0, crossAxisExtent: 826.0, crossAxisDirection:
AxisDirection.right, viewportMainAxisExtent: 805.0, remainingCacheExtent: 1305.0, cacheOrigin:
-250.0)
geometry: SliverGeometry(scrollExtent: 21000.0, paintExtent: 805.0, maxPaintExtent: 21000.0,
hasVisualOverflow: true, cacheExtent: 1305.0)
currently live children: 1 to 6
This RenderObject had the following descendants (showing up to depth 5):
child with index 1: RenderIndexedSemantics#9f23a
child: RenderRepaintBoundary#89623 NEEDS-PAINT
child: _RenderColoredBox#da96c NEEDS-PAINT
child: RenderPositionedBox#60e7f NEEDS-LAYOUT
child: RenderParagraph#3e200 relayoutBoundary=up1 NEEDS-LAYOUT
child with index 2: RenderIndexedSemantics#cd9d3
child: RenderRepaintBoundary#04b11 NEEDS-PAINT
child: _RenderColoredBox#d3dc9 NEEDS-PAINT
child: RenderPositionedBox#d0f81 NEEDS-LAYOUT
child: RenderParagraph#6065a relayoutBoundary=up1 NEEDS-LAYOUT
child with index 5: RenderIndexedSemantics#5f68d NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
child: RenderRepaintBoundary#ed0b9 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
child: _RenderColoredBox#b737d NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
child: RenderPositionedBox#2daac NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
child: RenderParagraph#26a3e NEEDS-LAYOUT NEEDS-PAINT
child with index 6: RenderIndexedSemantics#4b2f1 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
child: RenderRepaintBoundary#93339 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
child: _RenderColoredBox#10147 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
child: RenderPositionedBox#a9025 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
child: RenderParagraph#23002 NEEDS-LAYOUT NEEDS-PAINT
════════════════════════════════════════════════════════════════════════════════════════════════════
Code sample
Code sample
See https://dartpad.dev/?id=d9f723468f22d4035dfcf90366802151.
Screenshots or Video
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
[Paste your logs here]Flutter Doctor output
Doctor output
[Paste your output here]Reactions are currently unavailable
Metadata
Metadata
Labels
P0Critical issues such as a build break or regressionCritical issues such as a build break or regressiona: error messageError messages from the Flutter frameworkError messages from the Flutter frameworkf: scrollingViewports, list views, slivers, etc.Viewports, list views, slivers, etc.found in release: 3.16Found to occur in 3.16Found to occur in 3.16found in release: 3.17Found to occur in 3.17Found to occur in 3.17frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
Activity
danagbemava-nc commentedon Nov 21, 2023
Reproducible using the code sample shared above.
Tested on
3.13,3.16&3.17.0-12.0.pre.39Labeling for further insight.
code sample (pasted for convenience)
flutter doctor -v
xster commentedon Nov 21, 2023
b/312248242 upstream
goderbauer commentedon Nov 21, 2023
cc @Piinks @chunhtai
Piinks commentedon Nov 22, 2023
Not sure where the issue is yet, but here is what I have found so far.
When I run the repro, I see
grid item 2is a small box towards the top. If I comment outfindChildIndexCallbackto see what happens without a crash, and push the button,grid item 2becomes a different widget, it is a large box further down the list. Additionally,grid item 2is being assigned different keys when this change happens.When it crashes instead, the custom grid layout from the customer code is determining that only index 2 needs to be laid out, and that children up to index 1 and after index 4 need to be disposed, but that seems like the wrong indices since it omits index 3. 🤔
Restoring
findChildIndexCallbackmeans that theSliverMultiBoxAdaptorElement._childElementsare manipulated duringperformRebuild. Looking at this in the crash/no-crash scenario, it looks like the childCount used in RenderSliverGrid.performLayout is not being updated when the child elements are manipulated. The childCount is what is firing the assertion and causing the crash.In the no-crash scenario it plays out like this:
Compared to the crashing scenario:
Other bits:
In RenderSliverGrid.performLayout, the childCount as well as the first and last indices of the prior layout pass are used to determine garbage collection along with the new first and last index provided by the SliverGridLayout (which is a custom one in the OP). It could be that RenderSliverGrid is not doing a good job of supporting children being removed and inserted like in this case.
This is what I have found so far, I will be out from here through the holiday. Passing it on to @chunhtai in case he discovers something while I am out!
chunhtai commentedon Nov 22, 2023
I found the root cause, in SliverGrid.performLayout, we assume the children's indices are continuous, but that is not true when you remove child in the middle during a rebuild.
I will put up a fix shortly
Fix SliverGrid garbage collection issue (#138915)
github-actions commentedon Dec 8, 2023
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.Fix SliverGrid garbage collection issue (flutter#138915)