Skip to content

SliverVariedExtentList does not respect itemCount when calling itemExtentBuilder #138912

@Piinks

Description

@Piinks

Is there an existing issue for this?

Steps to reproduce

  1. Run the example code below.
  2. It will crash with an out of range error since the itemExtentBuilder is being called in excess of the number of items in the list. Since itemCount is specified, I expect it would not have called for indices outside of that range.

Expected results

App works.

Alternatively, if I try to work around the issue by checking that I am within range, it can lead to other errors like incorrect scroll extent calculations and worse, app hanging. (see second sample)

Actual results

In first sample, app crashes for accessing an index out of range of the list.

In second sample, the app hangs because it is infinitely calling the item extent builder.

Code sample

Code sample 1
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  final List<double> numbers = [
    10, 20, 30, 40, 50,
  ];
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: const Text('Bug'),
        ),
        body: CustomScrollView(
          slivers: [
            SliverVariedExtentList.builder(
              itemCount: numbers.length,
              itemBuilder: (context, index) {
                return SizedBox(
                  height: numbers[index],
                  child: Text('Size ${numbers[index]}'),
                  );
              },
              itemExtentBuilder: (index, dimensions) {
                return numbers[index]; // App crashes
              },
            ),
          ],
        ),
      ),
    );
  }
}
Code sample 2
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  final List<double> numbers = [
    10, 20, 30, 40, 50,
  ];
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: const Text('Bug'),
        ),
        body: CustomScrollView(
          slivers: [
            SliverVariedExtentList.builder(
              itemCount: numbers.length,
              itemBuilder: (context, index) {
                return SizedBox(
                  height: numbers[index],
                  child: Text('Size ${numbers[index]}'),
                  );
              },
              itemExtentBuilder: (index, dimensions) {
                if (index >= numbers.length) {
                  return 0; // App hangs instead of crashing
                }
                return numbers[index];
              },
            ),
          ],
        ),
      ),
    );
  }
}

Screenshots or Video

No response

Logs

Logs (from code sample 1 crash scenario)
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
The following IndexError was thrown during performLayout():
RangeError (index): Index out of range: index should be less than 5: 5

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: RenderSliverVariedExtentList#0490b relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-PAINT:
  creator: SliverVariedExtentList ← Viewport ← IgnorePointer-[GlobalKey#37208] ← Semantics ← Listener
    ← _GestureSemantics ← RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#e2c18] ←
    Listener ← _ScrollableScope ← _ScrollSemantics-[GlobalKey#a52fa] ←
    NotificationListener<ScrollMetricsNotification> ← RepaintBoundary ← ⋯
  parentData: paintOffset=Offset(0.0, 0.0) (can use size)
  constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.idle,
    scrollOffset: 0.0, remainingPaintExtent: 603.0, crossAxisExtent: 641.0, crossAxisDirection:
    AxisDirection.right, viewportMainAxisExtent: 603.0, remainingCacheExtent: 853.0, cacheOrigin: 0.0)
  geometry: null
  no children current live
This RenderObject has no descendants.
════════════════════════════════════════════════════════════════════════════════════════════════════
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.
Another exception was thrown: Unexpected null value.

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.16.0, on macOS 14.0 23A344 darwin-arm64, locale
    en-US)
    • Flutter version 3.16.0 on channel stable at /Users/katelovett/dev/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision db7ef5bf9f (7 days ago), 2023-11-15 11:25:44 -0800
    • Engine revision 74d16627b9
    • Dart version 3.2.0
    • DevTools version 2.28.2

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/katelovett/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: /Applications/Android
      Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build
      11.0.12+0-b1504.28-7817840)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.3.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14E300c
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.2)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build
      11.0.12+0-b1504.28-7817840)

[✓] VS Code (version 1.84.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.60.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 14.0 23A344 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 119.0.6045.159

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listc: crashStack traces logged to the consolef: scrollingViewports, list views, slivers, etc.frameworkflutter/packages/flutter repository. See also f: labels.team-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions