Repository navigation
PrimaryScrollController attached to multiple scroll views in TabBarView's keep-alive tabs #81152
Copy link
Copy link
Open
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: error messageError messages from the Flutter frameworkError messages from the Flutter frameworkc: crashStack traces logged to the consoleStack traces logged to the consoled: api docsIssues with https://api.flutter.dev/Issues with https://api.flutter.dev/d: stackoverflowGood question for Stack OverflowGood question for Stack Overflowf: scrollingViewports, list views, slivers, etc.Viewports, list views, slivers, etc.found in release: 2.2Found to occur in 2.2Found to occur in 2.2frameworkflutter/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 onteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
Description
Recently, scroll views will auto generate a scrollbar on desktop. (?) In TabBarView, if we set every tab(with scrollable child like listview) keep-alive, then the auto generated scrollbar controller will attached to every tab. Then it will raise ScrollController attached to multiple scroll views. if we drag scrollbar after switching tab once.
Steps to Reproduce:
Run example code on desktop(windows/macOS):
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
bottom: TabBar(
tabs: [Tab(text: 'TAB A'), Tab(text: 'TAB B')],
controller: _tabController,
),
),
body: TabBarView(
controller: _tabController,
children: [
KeepAliveBuilder(builder: (ctx) => ChildPage(name: 'Tab A')),
KeepAliveBuilder(builder: (ctx) => ChildPage(name: 'Tab B')),
],
),
);
}
}
class ChildPage extends StatelessWidget {
final String name;
const ChildPage({Key? key, required this.name}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView(
children: List.generate(
20,
(index) => ListTile(
title: Text('$name: $index'),
),
),
);
}
}
class KeepAliveBuilder extends StatefulWidget {
final WidgetBuilder builder;
final bool wantKeepAlive;
const KeepAliveBuilder(
{Key? key, required this.builder, this.wantKeepAlive = true})
: super(key: key);
@override
_KeepAliveBuilderState createState() => _KeepAliveBuilderState(wantKeepAlive);
}
class _KeepAliveBuilderState extends State<KeepAliveBuilder>
with AutomaticKeepAliveClientMixin {
bool _wantKeepAlive;
_KeepAliveBuilderState(this._wantKeepAlive);
@override
Widget build(BuildContext context) {
super.build(context);
return widget.builder(context);
}
@override
bool get wantKeepAlive => _wantKeepAlive;
}Expected results:
Actual results:
Logs
error
======== Exception caught by gesture ===============================================================
The following assertion was thrown while handling a gesture:
ScrollController attached to multiple scroll views.
'package:flutter/src/widgets/scroll_controller.dart':
Failed assertion: line 109 pos 12: '_positions.length == 1'
Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=2_bug.md
When the exception was thrown, this was the stack:
#2 ScrollController.position (package:flutter/src/widgets/scroll_controller.dart:109:12)
#3 RawScrollbarState.getScrollbarDirection (package:flutter/src/widgets/scrollbar.dart:1080:34)
#4 RawScrollbarState.handleThumbPressStart (package:flutter/src/widgets/scrollbar.dart:1103:29)
#5 _MaterialScrollbarState.handleThumbPressStart (package:flutter/src/material/scrollbar.dart:388:11)
#6 RawScrollbarState._gestures.<anonymous closure>.<anonymous closure> (package:flutter/src/widgets/scrollbar.dart:1239:74)
...
Handler: "onLongPressStart"
Recognizer: _ThumbPressGestureRecognizer#0c12c
debugOwner: _MaterialScrollbarState#6eb61(tickers: tracking 2 tickers)
state: possible
====================================================================================================
flutter doctor -v
[✓] Flutter (Channel master, 2.2.0-11.0.pre.274, on macOS 11.2.2 20D80 darwin-x64, locale en-CN)
• Flutter version 2.2.0-11.0.pre.274 at /Users/narumi/Library/flutter-master
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision d1f73a1065 (33 hours ago), 2021-04-24 00:44:02 -0400
• Engine revision eba9efd1c3
• Dart version 2.14.0 (build 2.14.0-37.0.dev)
• Pub download mirror https://pub.flutter-io.cn
• Flutter download mirror https://storage.flutter-io.cn
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
• Android SDK at /Users/narumi/Library/Android/sdk
• Platform android-30, build-tools 30.0.2
• Java binary at: /Users/narumi/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/201.6953283/Android
Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 12.4, Build version 12D4e
• CocoaPods version 1.10.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio
• Android Studio at /Users/narumi/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-1/202.7094744/Android Studio 4.2
Preview.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.8+10-b944.6916264)
[✓] Android Studio (version 4.1)
• Android Studio at /Users/narumi/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/201.6953283/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 1.8.0_242-release-1644-b3-6915495)
[✓] VS Code (version 1.55.0)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.21.0
[!] Proxy Configuration
• HTTP_PROXY is set
! NO_PROXY is not set
[✓] Connected device (2 available)
• macOS (desktop) • macos • darwin-x64 • macOS 11.2.2 20D80 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 90.0.4430.85
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work lista: error messageError messages from the Flutter frameworkError messages from the Flutter frameworkc: crashStack traces logged to the consoleStack traces logged to the consoled: api docsIssues with https://api.flutter.dev/Issues with https://api.flutter.dev/d: stackoverflowGood question for Stack OverflowGood question for Stack Overflowf: scrollingViewports, list views, slivers, etc.Viewports, list views, slivers, etc.found in release: 2.2Found to occur in 2.2Found to occur in 2.2frameworkflutter/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 onteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
Activity
pedromassangocode commentedon Apr 26, 2021
Hi @narumishi
Can you please provide the steps to reproduce this issue? I cannot reproduce this on latest master/stable channel.
Thank you
narumi147 commentedon Apr 26, 2021
@pedromassango please use the example code and build on desktop(macOS/windows tested). It seems scrollbar is not auto implemented on mobile.
pedromassangocode commentedon Apr 26, 2021
Hi @narumishi
I just build on MacOS desktop but I was unable to reproduce this issue (I got no crash). Tested on master and stable channel.
narumi147 commentedon Apr 26, 2021
@pedromassangocode
So strange, I have tested on both macOS and windows, debug/release mode, master channel. And they all raise such error.
Please check the detail steps:
ListViewwith an auto-generated scrollbar which will be visible when scrolling.pedromassangocode commentedon Apr 27, 2021
Thanks.
I was able to reproduce the issue following the steps in the comment above.
logs
flutter doctor -v
[✓] Flutter (Channel master, 2.3.0-1.0.pre.101, on macOS 11.2.3 20D91 darwin-x64, locale en-AO) • Flutter version 2.3.0-1.0.pre.101 at /Users/pedromassango/Code/flutter_master • Upstream repository https://github.com/flutter/flutter.git • Framework revision ff2dde2c7f (68 minutes ago), 2021-04-26 22:35:45 -0700 • Engine revision afd9c397a5 • Dart version 2.14.0 (build 2.14.0-43.0.dev) [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2) • Android SDK at /Users/pedromassango/Library/Android/sdk • Platform android-30, build-tools 30.0.2 • ANDROID_HOME = /Users/pedromassango/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495) • All Android licenses accepted. [!] Xcode - develop for iOS and macOS • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 12.4, Build version 12D4e ! CocoaPods 1.9.3 out of date (1.10.0 is recommended). CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side. Without CocoaPods, plugins will not work on iOS or macOS. For more info, see https://flutter.dev/platform-plugins To upgrade see https://guides.cocoapods.org/using/getting-started.html#installation for instructions. [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 4.1) • 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 1.8.0_242-release-1644-b3-6915495) [✓] IntelliJ IDEA Community Edition (version 2021.1) • IntelliJ at /Applications/IntelliJ IDEA CE.app • Flutter plugin version 55.1.5 • Dart plugin version 211.7179 [✓] VS Code (version 1.55.2) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.16.0 [✓] Connected device (2 available) • macOS (desktop) • macos • darwin-x64 • macOS 11.2.3 20D91 darwin-x64 • Chrome (web) • chrome • web-javascript • Google Chrome 90.0.4430.85 ! Doctor found issues in 1 category.goderbauer commentedon Apr 28, 2021
/cc @Piinks
24 remaining items
AhmedLSayed9 commentedon Apr 7, 2024
DavidOrakpo commentedon Jul 10, 2024
rusyaev-dk commentedon Aug 2, 2024
qwezey commentedon Oct 3, 2024
Piinks commentedon Oct 3, 2024
AhmedLSayed9 commentedon Mar 19, 2025
I can't reproduce this anymore using the latest stable version.
I think this is fixed by #157756 (available on flutter v3.29.0)
kobi666 commentedon Mar 19, 2025
same behavior is replicated on v3.29.1
AhmedLSayed9 commentedon Mar 19, 2025
I've testing this on Flutter v3.29.2, on both iOS & macOS (debug mode) and can't get any errors.
AhmedLSayed9 commentedon Mar 20, 2025
Well, the error has gone but the issue of scrolling in one tab causes the other tabs to scroll still exists. We've another issue for it too #159123
jasminder commentedon Mar 26, 2025
There are deeper issues related to this:
I am trying to scroll to a position. I have a NestedScrollView, with a tabbarbview. So, if I am on the first tab. and scroll it using an action. It works on that tab. However, if I change the tabbar and come back to the main tab and then try to scroll again. It gives me the error that:
ScrollController attached to multiple scroll views.
So, I guess both tabbarviews have this controller. I am using the following code to access the scrollController inside the body of NestedScrollView:
final innerScrollController = PrimaryScrollController.of(context);
jasminder commentedon Apr 2, 2025
I think that is for a specific case where you know the itemExtent for CustomScrollView. If you are using an other scrollview and you have dynamic height rows, scrolling gets messed up. It does solve the other issue, but it creates a new one as when you try to scroll back to top, it starts showing SliverToBoxAdapter (header) event before inner scroll view is all the way to top. I have a very specific use case, where on the first tab, I have various widgets of different heights, then a reorderablelistview which further has different height rows. If I use CustomScrollView, I get error that SliverOverlapInjector has found no absorbed extent to inject.
surajgju commentedon Aug 11, 2026
Hi @narumi147 and Flutter team 👋
I have identified the root cause of this issue and developed a fix with full test coverage.
Root Cause
When
TabBarViewchildren useAutomaticKeepAliveClientMixin, inactive tabs remain mounted in the element tree. Previously,TabBarViewpassed down the ancestorPrimaryScrollControllerto all tabs without scoping. As a result, scroll views in both active and kept-alive inactive tabs attached to the ancestorPrimaryScrollControllersimultaneously. When any interaction accessedPrimaryScrollController.position(such as desktop scrollbar dragging or iOS status-bar tap), an assertion error was thrown:ScrollController attached to multiple scroll views.Solution
Scope
PrimaryScrollControllerinside_TabBarViewState._updateChildren():tabIndex == _currentIndex): Inherits and forwards the ancestorPrimaryScrollController.tabIndex != _currentIndex): Wrapped inPrimaryScrollController.none(child: child).Wrapping both active and inactive tabs in
PrimaryScrollControllerwidgets keeps the widget tree depth (KeyedSubtree -> Semantics -> PrimaryScrollController -> child) identical across active and inactive states. Switching tabs updates thePrimaryScrollControllerproperties in place without unmounting or disposing kept-alive tab states.PR is being submitted shortly!
Fix PrimaryScrollController attached to multiple scroll views in TabB…
surajgju commentedon Aug 11, 2026
similiar open issues those can be fixed with this pr
#148317
#89864
#159123