riverpod
riverpod copied to clipboard
if a ref operation initializes a provider and throws, the stacktrace should be unmodified
Edit (Remi): The issue is that if the very first read of a provider throws, the stacktrace is effectively duplicated
Describe the bug If a provider emits an error synchronously when the app starts, the stack trace will be very long and different from when it is emitted later after the app starts.
To Reproduce
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(
const ProviderScope(child: MaterialApp(home: MyHomePage())),
);
}
final someProvider = FutureProvider((ref) {
throw UnimplementedError();
});
class MyHomePage extends ConsumerStatefulWidget {
const MyHomePage({super.key});
@override
ConsumerState<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends ConsumerState<MyHomePage> {
// Setting this to true initially, will lead to very long StackTrace.
bool enableWatch = true;
@override
Widget build(BuildContext context) {
if (enableWatch) log(ref.watch(someProvider).toString());
return Scaffold(
body: ElevatedButton(
onPressed: () {
setState(() {
enableWatch = true;
});
},
child: const Text('enable watch'),
),
);
}
}
Setting enableWatch to false and enabling it using the button later after the app starts will log the expected StackTrace.
What's the current vs expected behavior?
The following logs are from the same provider but the first one is when the provider is watched directly when runApp loads and the second one is when the provider is watched manually later after runApp loads.
I expect the first log to match the second log:
- When the error is thrown synchronously at app start:
[log] AsyncError<Never>(error: UnimplementedError, stackTrace: #0 someProvider.<anonymous closure> (package:testapp/main2.dart:13:3)
#1 FutureProvider._create (package:riverpod/src/future_provider/base.dart:65:65)
#2 FutureProviderElement.create.<anonymous closure> (package:riverpod/src/future_provider/base.dart:104:22)
#3 FutureHandlerProviderElementMixin.handleFuture.<anonymous closure> (package:riverpod/src/async_notifier/base.dart:323:30)
#4 FutureHandlerProviderElementMixin._handleAsync (package:riverpod/src/async_notifier/base.dart:370:47)
#5 FutureHandlerProviderElementMixin.handleFuture (package:riverpod/src/async_notifier/base.dart:317:5)
#6 FutureProviderElement.create (package:riverpod/src/future_provider/base.dart:103:5)
#7 ProviderElementBase.buildState (package:riverpod/src/framework/element.dart:425:7)
#8 ProviderElementBase.mount (package:riverpod/src/framework/element.dart:248:5)
#9 _StateReader._create (package:riverpod/src/framework/container.dart:47:11)
#10 _StateReader.getElement (package:riverpod/src/framework/container.dart:35:61)
#11 ProviderContainer.readProviderElement.<anonymous closure> (package:riverpod/src/framework/container.dart:442:40)
#12 ProviderContainer.readProviderElement (package:riverpod/src/framework/container.dart:477:8)
#13 ProviderBase.addListener (package:riverpod/src/framework/provider_base.dart:77:26)
#14 ProviderContainer.listen (package:riverpod/src/framework/container.dart:285:21)
#15 ConsumerStatefulElement.watch.<anonymous closure> (package:flutter_riverpod/src/consumer.dart:560:25)
#16 _LinkedHashMapMixin.putIfAbsent (dart:collection-patch/compact_hash.dart:535:23)
#17 ConsumerStatefulElement.watch (package:flutter_riverpod/src/consumer.dart:553:26)
#18 _MyHomePageState.build (package:testapp/main2.dart:29:30)
#19 StatefulElement.build (package:flutter/src/widgets/framework.dart:5198:27)
#20 ConsumerStatefulElement.build (package:flutter_riverpod/src/consumer.dart:542:20)
#21 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5086:15)
#22 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
#23 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#24 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#25 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5242:11)
#26 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#27 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#28 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#29 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6435:14)
#30 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#31 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#32 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5111:16)
#33 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#34 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#35 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#36 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#37 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#38 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6435:14)
#39 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#40 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#41 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6435:14)
#42 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#43 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#44 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5111:16)
#45 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
#46 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#47 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#48 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5242:11)
#49 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#50 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#51 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#52 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6435:14)
#53 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#54 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#55 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5111:16)
#56 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
#57 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#58 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#59 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5242:11)
#60 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#61 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#62 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#63 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6435:14)
#64 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#65 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#66 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5111:16)
#67 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
#68 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#69 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#70 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5242:11)
#71 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#72 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#73 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#74 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5111:16)
#75 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
#76 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#77 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#78 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5242:11)
#79 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#80 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#81 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#82 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6435:14)
#83 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#84 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#85 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5111:16)
#86 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
#87 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#88 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#89 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5242:11)
#90 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#91 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#92 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#93 SingleChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6435:14)
#94 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#95 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#96 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5111:16)
#97 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
#98 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#99 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
(Removed repeated output lines from 100~700)
#701 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#702 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#703 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#704 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#705 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#706 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5111:16)
#707 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
#708 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#709 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#710 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5242:11)
#711 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#712 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#713 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#714 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5111:16)
#715 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#716 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#717 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#718 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#719 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#720 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5111:16)
#721 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#722 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5068:5)
#723 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5062:5)
#724 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3971:16)
#725 Element.updateChild (package:flutter/src/widgets/framework.dart:3708:18)
#726 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1240:16)
#727 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1209:5)
#728 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1156:18)
#729 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2720:19)
#730 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1155:13)
#731 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:988:7)
#732 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:968:7)
#733 Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:18:15)
#734 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
#735 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
#736 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:189:12)
)
- When the error is thrown synchronously but later after the app starts (set
enableWatchto false and press the button):
[log] AsyncError<Never>(error: UnimplementedError, stackTrace: #0 someProvider.<anonymous closure> (package:testapp/main2.dart:13:3)
#1 FutureProvider._create (package:riverpod/src/future_provider/base.dart:65:65)
#2 FutureProviderElement.create.<anonymous closure> (package:riverpod/src/future_provider/base.dart:104:22)
#3 FutureHandlerProviderElementMixin.handleFuture.<anonymous closure> (package:riverpod/src/async_notifier/base.dart:323:30)
#4 FutureHandlerProviderElementMixin._handleAsync (package:riverpod/src/async_notifier/base.dart:370:47)
#5 FutureHandlerProviderElementMixin.handleFuture (package:riverpod/src/async_notifier/base.dart:317:5)
#6 FutureProviderElement.create (package:riverpod/src/future_provider/base.dart:103:5)
#7 ProviderElementBase.buildState (package:riverpod/src/framework/element.dart:425:7)
#8 ProviderElementBase.mount (package:riverpod/src/framework/element.dart:248:5)
#9 _StateReader._create (package:riverpod/src/framework/container.dart:47:11)
#10 _StateReader.getElement (package:riverpod/src/framework/container.dart:35:61)
#11 ProviderContainer.readProviderElement.<anonymous closure> (package:riverpod/src/framework/container.dart:442:40)
#12 ProviderContainer.readProviderElement (package:riverpod/src/framework/container.dart:477:8)
#13 ProviderBase.addListener (package:riverpod/src/framework/provider_base.dart:77:26)
#14 ProviderContainer.listen (package:riverpod/src/framework/container.dart:285:21)
#15 ConsumerStatefulElement.watch.<anonymous closure> (package:flutter_riverpod/src/consumer.dart:560:25)
#16 _LinkedHashMapMixin.putIfAbsent (dart:collection-patch/compact_hash.dart:535:23)
#17 ConsumerStatefulElement.watch (package:flutter_riverpod/src/consumer.dart:553:26)
#18 _MyHomePageState.build (package:testapp/main2.dart:29:30)
#19 StatefulElement.build (package:flutter/src/widgets/framework.dart:5198:27)
#20 ConsumerStatefulElement.build (package:flutter_riverpod/src/consumer.dart:542:20)
#21 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5086:15)
#22 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
#23 Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
#24 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2780:19)
#25 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:903:21)
#26 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:358:5)
#27 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1284:15)
#28 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1214:9)
#29 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1072:5)
#30 _invoke (dart:ui/hooks.dart:142:13)
#31 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:359:5)
#32 _drawFrame (dart:ui/hooks.dart:112:31)
)
The first log with hundreds of lines should be collapsed by https://github.com/flutter/flutter/issues/4174 but I'm not sure if this is only related to Flutter as the second log will still be different from the first log.
Eh If there's an easy way out, sure. But honestly I don't think it's a big deal, right?
Well, It's a bit annoying when these stack traces are reported to Crashlytics but I guess it's a low probability to occur.