riverpod
riverpod copied to clipboard
Unexpected "Providers are not allowed to modify other providers during their initialization" error
Describe the bug
Creating this issue as suggested in discord
I got this error: Providers are not allowed to modify other providers during their initialization
while updating notifier's state inside a ref.listen
's listener. Multiple providers are involved, the dependencies:
-
MyNotifier
->data3
->data
-
combine
- ->
data2
->data
- ->
MyNotifier
- ->
The possibility is that the ref.listen
's listener is called at the same time as the combine
provider is still re-building.
Log:
provider start
provider end
provider start
set new state <-- here is changing the notifier's state while the provider is still building
provider end
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: 'package:riverpod/src/framework/element.dart': Failed assertion: line 477 pos 11: '_debugCurrentlyBuildingElement == null ||
_debugCurrentlyBuildingElement == this': Providers are not allowed to modify other providers during their initialization.
Tried with versions:
- Flutter 3.13.9, flutter_riverpod 2.4.9
- Flutter 3.19.3, flutter_riverpod 2.5.1 and 3.0.0-dev3
To Reproduce
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() => runApp(const ProviderScope(child: MyPage()));
class MyPage extends ConsumerWidget {
const MyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
ref.watch(combine);
return MaterialApp(
home: Scaffold(
body: Text(ref.watch(myNotifierProvider).toString()),
));
}
}
final data = FutureProvider.autoDispose((ref) async {
await Future.delayed(
const Duration(seconds: 1)); // Simulating network request
return 'data';
});
final data2 = Provider.autoDispose((ref) => ref.watch(data).valueOrNull);
final data3 = Provider.autoDispose((ref) => ref.watch(data2));
final myNotifierProvider =
AutoDisposeNotifierProvider<MyNotifier, int>(() => MyNotifier());
class MyNotifier extends AutoDisposeNotifier<int> {
@override
build() {
// change to return ref.watch to fix
ref.listen(
data3,
(previous, next) {
print('set new state');
state = 1;
},
);
return 0;
}
}
final combine = Provider.autoDispose((ref) {
print('provider start');
ref.watch(data2);
// ref.watch(data3); // uncomment this to fix
ref.watch(
myNotifierProvider.select((value) => value)); // or remove select to fix
print('provider end');
return 0;
});
Expected behavior
There should be no error, or perhaps the listeners and provider building shouldn't be called at the same time