riverpod icon indicating copy to clipboard operation
riverpod copied to clipboard

if a ref operation initializes a provider and throws, the stacktrace should be unmodified

Open AhmedLSayed9 opened this issue 2 years ago • 5 comments
trafficstars

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.

AhmedLSayed9 avatar Aug 17 '23 02:08 AhmedLSayed9

What's the current vs expected behavior?

rrousselGit avatar Aug 17 '23 06:08 rrousselGit

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 enableWatch to 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)
)

AhmedLSayed9 avatar Aug 17 '23 07:08 AhmedLSayed9

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.

AhmedLSayed9 avatar Aug 17 '23 07:08 AhmedLSayed9

Eh If there's an easy way out, sure. But honestly I don't think it's a big deal, right?

rrousselGit avatar Aug 17 '23 11:08 rrousselGit

Well, It's a bit annoying when these stack traces are reported to Crashlytics but I guess it's a low probability to occur.

AhmedLSayed9 avatar Aug 17 '23 13:08 AhmedLSayed9