Using ref.watch/ref.listen on mutation in a widget produces "(setState() or markNeedsBuild() called during build." error
Open
s9th
opened this issue 3 months ago
•
25 comments
Describe the bug
I have a root widget with 4 listeners set up. Two of them on regular notifiers and two on mutations.
If I turn on All Exceptions in the debugger, when riverpod starts adding the listener on the first of the mutations, the following error is thrown during the first build
Exception has occurred.
FlutterError (setState() or markNeedsBuild() called during build.
This UncontrolledProviderScope widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
UncontrolledProviderScope
The widget which was currently being built when the offending call was made was:
LockScreen)
I've tested it by removing the listener, and the error was then thrown inside another widget with a mutation watch/listen.
FlutterError (setState() or markNeedsBuild() called during build.
This UncontrolledProviderScope widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
UncontrolledProviderScope
The widget which was currently being built when the offending call was made was:
ProfilesList)
Hello @rrousselGit , could you give us a quick update on this issue? I'm also experiencing it on other projects, and I'm wondering if it's critical or if we can continue working despite this exception. Thank you.
I solved this by adding WidgetsBinding.instance.addPostFrameCallback((_) in the build. It avoids to trigger the update while building the frame. Drawback is that you get a bit of delay on the redraw (e.g., when moving through router pages).
Widget build(BuildContext context) {
// Using addPostFrameCallback to avoid calling watch during build and getting exception
WidgetsBinding.instance.addPostFrameCallback((_) {
qualities = ref.watch(qualitiesProvider);
numQualities = qualities.length;
defectNames = ref.watch(currentDefectNamesProvider);
numDefects = defectNames.length;
});
return Material(
[...]
Not the real solution, but a quick patch to keep the code working.
Hello,
https://github.com/rrousselGit/riverpod/issues/4285#issuecomment-3285786415
I upgraded to 3.0.2, still have this issue.
I'm adding a few screenshots if that helps to provide more context to my previous message.
Thank you
This happens to me as well. However, it doesn't seem to be critical. The app is running normally and I get this exception only when All Exceptions is ticked, which means it's handled somewhere. Would be nice not to have it though.
This happens to me as well. However, it doesn't seem to be critical. The app is running normally and I get this exception only when All Exceptions is ticked, which means it's handled somewhere. Would be nice not to have it though.
Apps run normally, but widget tests fail on this issue. Interestingly, only a few combinations of providers and widgets suffer from this. It also happens with regular providers without mutations.
FlutterError (setState() or markNeedsBuild() called during build.
This UncontrolledProviderScope widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
UncontrolledProviderScope
The widget which was currently being built when the offending call was made was:
MyWidget)
Unluckily I'm not sure how to capture a FlutterError handled by the framework to make a test fail.
Here's the self-enclosing test I'm trying to write (with no luck, as the following passes):
self-enclosing test
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/experimental/mutation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets("ProviderScope wont't rebuild if watching a mutation", (t) async {
await t.pumpWidget(const ProviderScope(child: MyWidget()));
await t.pumpAndSettle();
final e = t.takeException();
expect(e, isNull);
final container = t.container();
expect(container.read(counterProvider), equals(0));
});
}
class MyWidget extends ConsumerWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final mutation = ref.watch(CounterNotifier.mutation);
final counter = ref.watch(counterProvider);
return Directionality(
textDirection: TextDirection.ltr,
child: Material(
child: Center(
child: TextButton(
onPressed: () async {
await CounterNotifier.mutation.run(ref, (tsx) async {
await tsx.get(counterProvider.notifier).increment();
});
},
child: Text('Counter: $counter, Mutation State: $mutation'),
),
),
),
);
}
}
final NotifierProvider<CounterNotifier, int> counterProvider =
NotifierProvider.autoDispose<CounterNotifier, int>(
CounterNotifier.new,
);
class CounterNotifier extends Notifier<int> {
@override
int build() {
return 0;
}
static Mutation<void> get mutation => Mutation<void>();
Future<void> increment() async {
await Future<void>.delayed(const Duration(seconds: 1));
state = state + 1;
}
}
In the app, it occurs only with "Pause on All exceptions".
In widget tests, it causes a test failure (Exception caught by Flutter test framework). Unfortunately, I have not been able to create an isolated test.
Log of a test failure (with 7 exceptions)
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test:
setState() or markNeedsBuild() called during build.
This EditUserSmallPane widget cannot be marked as needing to build because the framework is already
in the process of building widgets. A widget can be marked as needing to be built during the build
phase only if one of its ancestors is currently building. This exception is allowed because the
framework builds parent widgets before children, which means a dirty descendant will always be
built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
EditUserSmallPane
The widget which was currently being built when the offending call was made was:
DeleteAccountButton
The test description was:
matches golden file (320x1600)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test (but after the test had completed):
setState() or markNeedsBuild() called during build.
This UserPictureStandaloneField widget cannot be marked as needing to build because the framework is
already in the process of building widgets. A widget can be marked as needing to be built during the
build phase only if one of its ancestors is currently building. This exception is allowed because
the framework builds parent widgets before children, which means a dirty descendant will always be
built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
UserPictureStandaloneField
The widget which was currently being built when the offending call was made was:
DeleteAccountButton
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild. (package:flutter/src/widgets/framework.dart:5279:9)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5291:6)
#2 ConsumerStatefulElement.watch.. (package:flutter_riverpod/src/core/consumer.dart:453:28)
#3 InternalProviderContainer.runBinaryGuarded (package:riverpod/src/core/provider_container.dart:679:9)
#4 ProviderSubscriptionImpl._notifyData (package:riverpod/src/core/provider_subscription.dart:181:32)
#5 InternalProviderContainer.runBinaryGuarded (package:riverpod/src/core/provider_container.dart:679:9)
#6 ProviderElement._notifyListeners (package:riverpod/src/core/element.dart:820:21)
#7 ProviderElement._performRebuild (package:riverpod/src/core/element.dart:582:9)
#8 ProviderElement.flush (package:riverpod/src/core/element.dart:626:7)
#9 ProviderElement._maybeRebuildDependencies. (package:riverpod/src/core/element.dart:639:41)
#10 ProviderElement.visitAncestors (package:riverpod/src/core/element.dart:1300:16)
#11 ProviderElement._maybeRebuildDependencies (package:riverpod/src/core/element.dart:639:5)
#12 ProviderElement.flush (package:riverpod/src/core/element.dart:623:5)
#13 ProviderSubX.readSafe (package:riverpod/src/core/provider_subscription.dart:80:27)
#14 ConsumerStatefulElement.watch (package:flutter_riverpod/src/core/consumer.dart:458:14)
#15 DeleteAccountButton.build (package:managry_users/src/client/ui/entities/user/account/_delete_account_button.dart:24:67)
#16 _ConsumerState.build (package:flutter_riverpod/src/core/consumer.dart:283:48)
#17 StatefulElement.build (package:flutter/src/widgets/framework.dart:5833:27)
#18 ConsumerStatefulElement.build (package:flutter_riverpod/src/core/consumer.dart:421:20)
#19 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5723:15)
#20 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5884:11)
#21 Element.rebuild (package:flutter/src/widgets/framework.dart:5435:7)
#22 BuildScope._tryRebuild (package:flutter/src/widgets/framework.dart:2695:15)
#23 BuildScope._flushDirtyElements (package:flutter/src/widgets/framework.dart:2752:11)
#24 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:3056:18)
#25 _LayoutBuilderElement._rebuildWithConstraints (package:flutter/src/widgets/layout_builder.dart:271:12)
#26 RenderAbstractLayoutBuilderMixin.layoutCallback (package:flutter/src/widgets/layout_builder.dart:334:38)
#27 RenderObjectWithLayoutCallbackMixin.runLayoutCallback. (package:flutter/src/rendering/object.dart:4156:33)
#28 RenderObject.invokeLayoutCallback. (package:flutter/src/rendering/object.dart:2881:17)
#29 PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1206:15)
#30 RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2880:14)
#31 RenderObjectWithLayoutCallbackMixin.runLayoutCallback (package:flutter/src/rendering/object.dart:4156:5)
#32 _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:448:5)
#33 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#34 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#35 _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1481:11)
#36 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#37 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#38 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#39 RenderConstrainedOverflowBox.performLayout (package:flutter/src/rendering/shifted_box.dart:717:14)
#40 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2610:7)
#41 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1157:18)
#42 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1170:15)
#43 AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1508:27)
#44 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:495:5)
#45 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1434:15)
#46 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1347:9)
#47 AutomatedTestWidgetsFlutterBinding.pump. (package:flutter_test/src/binding.dart:1335:9)
#50 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:74:41)
#51 AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1324:27)
#52 WidgetTester.pumpAndSettle. (package:flutter_test/src/widget_tester.dart:719:23)
#53 TestAsyncUtils.guard. (package:flutter_test/src/test_async_utils.dart:130:27)
#54 UnitTester.pumpWidget. (package:managry_theme/src/test/unit_tester.dart:79:9)
#56 UnitTester.pumpWidget (package:managry_theme/src/test/unit_tester.dart:75:5)
#57 wrappedGoldenFileTest. (package:managry_theme/src/test/wrapped_golden_file_test.dart:40:9)
#58 usersClientTest. (package:managry_users/src/test/users_client_test.dart:62:7)
#59 initializedTest. (package:managry_theme/src/test/initialized_test.dart:206:11)
#60 testWidgets.. (package:flutter_test/src/widget_tester.dart:192:15)
#61 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1059:5)
(elided 4 frames from dart:async and package:stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test (but after the test had completed):
setState() or markNeedsBuild() called during build.
This UserNameStandaloneField widget cannot be marked as needing to build because the framework is
already in the process of building widgets. A widget can be marked as needing to be built during the
build phase only if one of its ancestors is currently building. This exception is allowed because
the framework builds parent widgets before children, which means a dirty descendant will always be
built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
UserNameStandaloneField
The widget which was currently being built when the offending call was made was:
DeleteAccountButton
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild. (package:flutter/src/widgets/framework.dart:5279:9)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5291:6)
#2 ConsumerStatefulElement.watch.. (package:flutter_riverpod/src/core/consumer.dart:453:28)
#3 InternalProviderContainer.runBinaryGuarded (package:riverpod/src/core/provider_container.dart:679:9)
#4 ProviderSubscriptionImpl._notifyData (package:riverpod/src/core/provider_subscription.dart:181:32)
#5 InternalProviderContainer.runBinaryGuarded (package:riverpod/src/core/provider_container.dart:679:9)
#6 ProviderElement._notifyListeners (package:riverpod/src/core/element.dart:820:21)
#7 ProviderElement._performRebuild (package:riverpod/src/core/element.dart:582:9)
#8 ProviderElement.flush (package:riverpod/src/core/element.dart:626:7)
#9 ProviderElement._maybeRebuildDependencies. (package:riverpod/src/core/element.dart:639:41)
#10 ProviderElement.visitAncestors (package:riverpod/src/core/element.dart:1300:16)
#11 ProviderElement._maybeRebuildDependencies (package:riverpod/src/core/element.dart:639:5)
#12 ProviderElement.flush (package:riverpod/src/core/element.dart:623:5)
#13 ProviderSubX.readSafe (package:riverpod/src/core/provider_subscription.dart:80:27)
#14 ConsumerStatefulElement.watch (package:flutter_riverpod/src/core/consumer.dart:458:14)
#15 DeleteAccountButton.build (package:managry_users/src/client/ui/entities/user/account/_delete_account_button.dart:24:67)
#16 _ConsumerState.build (package:flutter_riverpod/src/core/consumer.dart:283:48)
#17 StatefulElement.build (package:flutter/src/widgets/framework.dart:5833:27)
#18 ConsumerStatefulElement.build (package:flutter_riverpod/src/core/consumer.dart:421:20)
#19 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5723:15)
#20 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5884:11)
#21 Element.rebuild (package:flutter/src/widgets/framework.dart:5435:7)
#22 BuildScope._tryRebuild (package:flutter/src/widgets/framework.dart:2695:15)
#23 BuildScope._flushDirtyElements (package:flutter/src/widgets/framework.dart:2752:11)
#24 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:3056:18)
#25 _LayoutBuilderElement._rebuildWithConstraints (package:flutter/src/widgets/layout_builder.dart:271:12)
#26 RenderAbstractLayoutBuilderMixin.layoutCallback (package:flutter/src/widgets/layout_builder.dart:334:38)
#27 RenderObjectWithLayoutCallbackMixin.runLayoutCallback. (package:flutter/src/rendering/object.dart:4156:33)
#28 RenderObject.invokeLayoutCallback. (package:flutter/src/rendering/object.dart:2881:17)
#29 PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1206:15)
#30 RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2880:14)
#31 RenderObjectWithLayoutCallbackMixin.runLayoutCallback (package:flutter/src/rendering/object.dart:4156:5)
#32 _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:448:5)
#33 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#34 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#35 _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1481:11)
#36 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#37 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#38 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#39 RenderConstrainedOverflowBox.performLayout (package:flutter/src/rendering/shifted_box.dart:717:14)
#40 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2610:7)
#41 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1157:18)
#42 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1170:15)
#43 AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1508:27)
#44 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:495:5)
#45 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1434:15)
#46 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1347:9)
#47 AutomatedTestWidgetsFlutterBinding.pump. (package:flutter_test/src/binding.dart:1335:9)
#50 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:74:41)
#51 AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1324:27)
#52 WidgetTester.pumpAndSettle. (package:flutter_test/src/widget_tester.dart:719:23)
#53 TestAsyncUtils.guard. (package:flutter_test/src/test_async_utils.dart:130:27)
#54 UnitTester.pumpWidget. (package:managry_theme/src/test/unit_tester.dart:79:9)
#56 UnitTester.pumpWidget (package:managry_theme/src/test/unit_tester.dart:75:5)
#57 wrappedGoldenFileTest. (package:managry_theme/src/test/wrapped_golden_file_test.dart:40:9)
#58 usersClientTest. (package:managry_users/src/test/users_client_test.dart:62:7)
#59 initializedTest. (package:managry_theme/src/test/initialized_test.dart:206:11)
#60 testWidgets.. (package:flutter_test/src/widget_tester.dart:192:15)
#61 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1059:5)
(elided 4 frames from dart:async and package:stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test (but after the test had completed):
setState() or markNeedsBuild() called during build.
This EmailBlock widget cannot be marked as needing to build because the framework is already in the
process of building widgets. A widget can be marked as needing to be built during the build phase
only if one of its ancestors is currently building. This exception is allowed because the framework
builds parent widgets before children, which means a dirty descendant will always be built.
Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
EmailBlock
The widget which was currently being built when the offending call was made was:
DeleteAccountButton
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild. (package:flutter/src/widgets/framework.dart:5279:9)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5291:6)
#2 ConsumerStatefulElement.watch.. (package:flutter_riverpod/src/core/consumer.dart:453:28)
#3 InternalProviderContainer.runBinaryGuarded (package:riverpod/src/core/provider_container.dart:679:9)
#4 ProviderSubscriptionImpl._notifyData (package:riverpod/src/core/provider_subscription.dart:181:32)
#5 InternalProviderContainer.runBinaryGuarded (package:riverpod/src/core/provider_container.dart:679:9)
#6 ProviderElement._notifyListeners (package:riverpod/src/core/element.dart:820:21)
#7 ProviderElement._performRebuild (package:riverpod/src/core/element.dart:582:9)
#8 ProviderElement.flush (package:riverpod/src/core/element.dart:626:7)
#9 ProviderElement._maybeRebuildDependencies. (package:riverpod/src/core/element.dart:639:41)
#10 ProviderElement.visitAncestors (package:riverpod/src/core/element.dart:1300:16)
#11 ProviderElement._maybeRebuildDependencies (package:riverpod/src/core/element.dart:639:5)
#12 ProviderElement.flush (package:riverpod/src/core/element.dart:623:5)
#13 ProviderSubX.readSafe (package:riverpod/src/core/provider_subscription.dart:80:27)
#14 ConsumerStatefulElement.watch (package:flutter_riverpod/src/core/consumer.dart:458:14)
#15 DeleteAccountButton.build (package:managry_users/src/client/ui/entities/user/account/_delete_account_button.dart:24:67)
#16 _ConsumerState.build (package:flutter_riverpod/src/core/consumer.dart:283:48)
#17 StatefulElement.build (package:flutter/src/widgets/framework.dart:5833:27)
#18 ConsumerStatefulElement.build (package:flutter_riverpod/src/core/consumer.dart:421:20)
#19 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5723:15)
#20 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5884:11)
#21 Element.rebuild (package:flutter/src/widgets/framework.dart:5435:7)
#22 BuildScope._tryRebuild (package:flutter/src/widgets/framework.dart:2695:15)
#23 BuildScope._flushDirtyElements (package:flutter/src/widgets/framework.dart:2752:11)
#24 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:3056:18)
#25 _LayoutBuilderElement._rebuildWithConstraints (package:flutter/src/widgets/layout_builder.dart:271:12)
#26 RenderAbstractLayoutBuilderMixin.layoutCallback (package:flutter/src/widgets/layout_builder.dart:334:38)
#27 RenderObjectWithLayoutCallbackMixin.runLayoutCallback. (package:flutter/src/rendering/object.dart:4156:33)
#28 RenderObject.invokeLayoutCallback. (package:flutter/src/rendering/object.dart:2881:17)
#29 PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1206:15)
#30 RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2880:14)
#31 RenderObjectWithLayoutCallbackMixin.runLayoutCallback (package:flutter/src/rendering/object.dart:4156:5)
#32 _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:448:5)
#33 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#34 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#35 _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1481:11)
#36 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#37 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#38 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#39 RenderConstrainedOverflowBox.performLayout (package:flutter/src/rendering/shifted_box.dart:717:14)
#40 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2610:7)
#41 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1157:18)
#42 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1170:15)
#43 AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1508:27)
#44 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:495:5)
#45 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1434:15)
#46 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1347:9)
#47 AutomatedTestWidgetsFlutterBinding.pump. (package:flutter_test/src/binding.dart:1335:9)
#50 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:74:41)
#51 AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1324:27)
#52 WidgetTester.pumpAndSettle. (package:flutter_test/src/widget_tester.dart:719:23)
#53 TestAsyncUtils.guard. (package:flutter_test/src/test_async_utils.dart:130:27)
#54 UnitTester.pumpWidget. (package:managry_theme/src/test/unit_tester.dart:79:9)
#56 UnitTester.pumpWidget (package:managry_theme/src/test/unit_tester.dart:75:5)
#57 wrappedGoldenFileTest. (package:managry_theme/src/test/wrapped_golden_file_test.dart:40:9)
#58 usersClientTest. (package:managry_users/src/test/users_client_test.dart:62:7)
#59 initializedTest. (package:managry_theme/src/test/initialized_test.dart:206:11)
#60 testWidgets.. (package:flutter_test/src/widget_tester.dart:192:15)
#61 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1059:5)
(elided 4 frames from dart:async and package:stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test (but after the test had completed):
setState() or markNeedsBuild() called during build.
This SuspendAccessButton widget cannot be marked as needing to build because the framework is
already in the process of building widgets. A widget can be marked as needing to be built during the
build phase only if one of its ancestors is currently building. This exception is allowed because
the framework builds parent widgets before children, which means a dirty descendant will always be
built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
SuspendAccessButton
The widget which was currently being built when the offending call was made was:
DeleteAccountButton
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild. (package:flutter/src/widgets/framework.dart:5279:9)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5291:6)
#2 ConsumerStatefulElement.watch.. (package:flutter_riverpod/src/core/consumer.dart:453:28)
#3 InternalProviderContainer.runBinaryGuarded (package:riverpod/src/core/provider_container.dart:679:9)
#4 ProviderSubscriptionImpl._notifyData (package:riverpod/src/core/provider_subscription.dart:181:32)
#5 InternalProviderContainer.runBinaryGuarded (package:riverpod/src/core/provider_container.dart:679:9)
#6 ProviderElement._notifyListeners (package:riverpod/src/core/element.dart:820:21)
#7 ProviderElement._performRebuild (package:riverpod/src/core/element.dart:582:9)
#8 ProviderElement.flush (package:riverpod/src/core/element.dart:626:7)
#9 ProviderElement._maybeRebuildDependencies. (package:riverpod/src/core/element.dart:639:41)
#10 ProviderElement.visitAncestors (package:riverpod/src/core/element.dart:1300:16)
#11 ProviderElement._maybeRebuildDependencies (package:riverpod/src/core/element.dart:639:5)
#12 ProviderElement.flush (package:riverpod/src/core/element.dart:623:5)
#13 ProviderSubX.readSafe (package:riverpod/src/core/provider_subscription.dart:80:27)
#14 ConsumerStatefulElement.watch (package:flutter_riverpod/src/core/consumer.dart:458:14)
#15 DeleteAccountButton.build (package:managry_users/src/client/ui/entities/user/account/_delete_account_button.dart:24:67)
#16 _ConsumerState.build (package:flutter_riverpod/src/core/consumer.dart:283:48)
#17 StatefulElement.build (package:flutter/src/widgets/framework.dart:5833:27)
#18 ConsumerStatefulElement.build (package:flutter_riverpod/src/core/consumer.dart:421:20)
#19 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5723:15)
#20 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5884:11)
#21 Element.rebuild (package:flutter/src/widgets/framework.dart:5435:7)
#22 BuildScope._tryRebuild (package:flutter/src/widgets/framework.dart:2695:15)
#23 BuildScope._flushDirtyElements (package:flutter/src/widgets/framework.dart:2752:11)
#24 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:3056:18)
#25 _LayoutBuilderElement._rebuildWithConstraints (package:flutter/src/widgets/layout_builder.dart:271:12)
#26 RenderAbstractLayoutBuilderMixin.layoutCallback (package:flutter/src/widgets/layout_builder.dart:334:38)
#27 RenderObjectWithLayoutCallbackMixin.runLayoutCallback. (package:flutter/src/rendering/object.dart:4156:33)
#28 RenderObject.invokeLayoutCallback. (package:flutter/src/rendering/object.dart:2881:17)
#29 PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1206:15)
#30 RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2880:14)
#31 RenderObjectWithLayoutCallbackMixin.runLayoutCallback (package:flutter/src/rendering/object.dart:4156:5)
#32 _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:448:5)
#33 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#34 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#35 _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1481:11)
#36 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#37 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#38 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#39 RenderConstrainedOverflowBox.performLayout (package:flutter/src/rendering/shifted_box.dart:717:14)
#40 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2610:7)
#41 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1157:18)
#42 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1170:15)
#43 AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1508:27)
#44 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:495:5)
#45 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1434:15)
#46 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1347:9)
#47 AutomatedTestWidgetsFlutterBinding.pump. (package:flutter_test/src/binding.dart:1335:9)
#50 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:74:41)
#51 AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1324:27)
#52 WidgetTester.pumpAndSettle. (package:flutter_test/src/widget_tester.dart:719:23)
#53 TestAsyncUtils.guard. (package:flutter_test/src/test_async_utils.dart:130:27)
#54 UnitTester.pumpWidget. (package:managry_theme/src/test/unit_tester.dart:79:9)
#56 UnitTester.pumpWidget (package:managry_theme/src/test/unit_tester.dart:75:5)
#57 wrappedGoldenFileTest. (package:managry_theme/src/test/wrapped_golden_file_test.dart:40:9)
#58 usersClientTest. (package:managry_users/src/test/users_client_test.dart:62:7)
#59 initializedTest. (package:managry_theme/src/test/initialized_test.dart:206:11)
#60 testWidgets.. (package:flutter_test/src/widget_tester.dart:192:15)
#61 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1059:5)
(elided 4 frames from dart:async and package:stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test (but after the test had completed):
setState() or markNeedsBuild() called during build.
This SystemRolesStandaloneField widget cannot be marked as needing to build because the framework is
already in the process of building widgets. A widget can be marked as needing to be built during the
build phase only if one of its ancestors is currently building. This exception is allowed because
the framework builds parent widgets before children, which means a dirty descendant will always be
built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
SystemRolesStandaloneField
The widget which was currently being built when the offending call was made was:
DeleteAccountButton
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild. (package:flutter/src/widgets/framework.dart:5279:9)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:5291:6)
#2 ConsumerStatefulElement.watch.. (package:flutter_riverpod/src/core/consumer.dart:453:28)
#3 InternalProviderContainer.runBinaryGuarded (package:riverpod/src/core/provider_container.dart:679:9)
#4 ProviderSubscriptionImpl._notifyData (package:riverpod/src/core/provider_subscription.dart:181:32)
#5 InternalProviderContainer.runBinaryGuarded (package:riverpod/src/core/provider_container.dart:679:9)
#6 ProviderElement._notifyListeners (package:riverpod/src/core/element.dart:820:21)
#7 ProviderElement._performRebuild (package:riverpod/src/core/element.dart:582:9)
#8 ProviderElement.flush (package:riverpod/src/core/element.dart:626:7)
#9 ProviderElement._maybeRebuildDependencies. (package:riverpod/src/core/element.dart:639:41)
#10 ProviderElement.visitAncestors (package:riverpod/src/core/element.dart:1300:16)
#11 ProviderElement._maybeRebuildDependencies (package:riverpod/src/core/element.dart:639:5)
#12 ProviderElement.flush (package:riverpod/src/core/element.dart:623:5)
#13 ProviderSubX.readSafe (package:riverpod/src/core/provider_subscription.dart:80:27)
#14 ConsumerStatefulElement.watch (package:flutter_riverpod/src/core/consumer.dart:458:14)
#15 DeleteAccountButton.build (package:managry_users/src/client/ui/entities/user/account/_delete_account_button.dart:24:67)
#16 _ConsumerState.build (package:flutter_riverpod/src/core/consumer.dart:283:48)
#17 StatefulElement.build (package:flutter/src/widgets/framework.dart:5833:27)
#18 ConsumerStatefulElement.build (package:flutter_riverpod/src/core/consumer.dart:421:20)
#19 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5723:15)
#20 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5884:11)
#21 Element.rebuild (package:flutter/src/widgets/framework.dart:5435:7)
#22 BuildScope._tryRebuild (package:flutter/src/widgets/framework.dart:2695:15)
#23 BuildScope._flushDirtyElements (package:flutter/src/widgets/framework.dart:2752:11)
#24 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:3056:18)
#25 _LayoutBuilderElement._rebuildWithConstraints (package:flutter/src/widgets/layout_builder.dart:271:12)
#26 RenderAbstractLayoutBuilderMixin.layoutCallback (package:flutter/src/widgets/layout_builder.dart:334:38)
#27 RenderObjectWithLayoutCallbackMixin.runLayoutCallback. (package:flutter/src/rendering/object.dart:4156:33)
#28 RenderObject.invokeLayoutCallback. (package:flutter/src/rendering/object.dart:2881:17)
#29 PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:1206:15)
#30 RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:2880:14)
#31 RenderObjectWithLayoutCallbackMixin.runLayoutCallback (package:flutter/src/rendering/object.dart:4156:5)
#32 _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:448:5)
#33 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#34 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#35 _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1481:11)
#36 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#37 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:115:18)
#38 RenderObject.layout (package:flutter/src/rendering/object.dart:2762:7)
#39 RenderConstrainedOverflowBox.performLayout (package:flutter/src/rendering/shifted_box.dart:717:14)
#40 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:2610:7)
#41 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1157:18)
#42 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:1170:15)
#43 AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1508:27)
#44 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:495:5)
#45 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1434:15)
#46 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1347:9)
#47 AutomatedTestWidgetsFlutterBinding.pump. (package:flutter_test/src/binding.dart:1335:9)
#50 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:74:41)
#51 AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:1324:27)
#52 WidgetTester.pumpAndSettle. (package:flutter_test/src/widget_tester.dart:719:23)
#53 TestAsyncUtils.guard. (package:flutter_test/src/test_async_utils.dart:130:27)
#54 UnitTester.pumpWidget. (package:managry_theme/src/test/unit_tester.dart:79:9)
#56 UnitTester.pumpWidget (package:managry_theme/src/test/unit_tester.dart:75:5)
#57 wrappedGoldenFileTest. (package:managry_theme/src/test/wrapped_golden_file_test.dart:40:9)
#58 usersClientTest. (package:managry_users/src/test/users_client_test.dart:62:7)
#59 initializedTest. (package:managry_theme/src/test/initialized_test.dart:206:11)
#60 testWidgets.. (package:flutter_test/src/widget_tester.dart:192:15)
#61 TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:1059:5)
(elided 4 frames from dart:async and package:stack_trace)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test (but after the test had completed):
setState() or markNeedsBuild() called during build.
This UsersProviderInitializer widget cannot be marked as needing to build because the framework is
already in the process of building widgets. A widget can be marked as needing to be built during the
build phase only if one of its ancestors is currently building. This exception is allowed because
the framework builds parent widgets before children, which means a dirty descendant will always be
built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
UsersProviderInitializer
The widget which was currently being built when the offending call was made was:
DeleteAccountButton
It makes no sense to say that this occurs only on "pause on all exceptions" but also that it happens inside widget tests.
Because if the pause doesn't happen unless you enable "all exceptions", then that's technically not a bug.
The error was caught and handled by Riverpod. You shouldn't care about it.
Bug failing tests are a very different story.
But I don't see a test case in this issue ; only IDE inconveniences
This also occurs for me only on "All Exceptions" (haven't used any widget tests while having this problem). However, I wouldn't want "All Exceptions" to be polluted with an exception that should probably not occur either way (unless it was designed this way).
To clarify, are all people seeing this using the Dart Debugger and "Pause on All Exceptions" (rather than just the uncaught ones)?
Yes. For now, that seems to be the case.
In the app, it occurs only with "Pause on All exceptions". In widget tests, it causes a test failure (Exception caught by Flutter test framework). Unfortunately, I have not been able to create an isolated test.
No. Your logs underline there's an issue on your code. There's no mention of UncontrolledProviderScope or anything related to riverpod, really. That might explain why you aren't to create an isolated test yet. Please, if I'm wrong, lend a hand and try to find out your issue (you might need to file a separate issue if you find anything, tbh, as it seems different).
But I don't see a test case in this issue ; only IDE inconveniences
That's not a minor inconvenience. Most folks, including me, exploit All Exceptions to find pesky bugs. It's just handy to have there.
Now, for each mutation your app watches, the error triggers.
Furthermore, considering this error triggers on every rebuild, can't this be a huge performance toll on the UI? e.g. animations?
It could very well be that the solution is to update the IDE to ignore exceptions thrown+caught inside packages
I wanted to double check but no, this is not the issue. I, likely as everyone else, am not debugging external code.
My VS Code settings clearly mention "Debug my code" down in the status bar. Other options mention "Debug my code + packages" and "Debug my code + packages + SDK". I'm using the first one (my and mine only).
This makes sense: the exception is thrown from the blamed widget, which is in my code: it's "The widget which was currently being built when the offending call was made was" Flutter is complaining about.
Indeed, as a further confirmation, the debugger stops at
final mutation = ref.watch(CounterNotifier.mutation); // Exception has occurred.
So I don't think this is solvable on "our" end, @rrousselGit.
Unluckily, I currently don't know how to write a test for this scenario.
I'm not saying there's something you should do. But it doesn't change the fact this is purely a "Developer experience" issue. There's no bug here.
VScode could be updated to ignore this error without Riverpod changing in any capacity.
I'll think of a better solution to avoid this inconvenience, but the behaviour of the application seems to be correct.
I’m also experiencing the same issue.
At first, I wasn’t sure if I was doing something wrong, but it seems to be the same behavior described here.
When the debugger is set to “Pause on All Exceptions” (as shown in my screenshot), VS Code behaves as if the debugger pauses automatically — the execution stops, and I have to press the Play ▶️ button to continue.
After that, the app runs normally, but it’s really annoying because it keeps interrupting the workflow even though nothing is actually broken.
I'm pulling my hair out for this issue, it just so happens that I turned on the All Exceptions by instinct to check a bug, and all of the sudden, all hell break loose 😆 . Thanks for pointing this out, I never would've notice it.