riverpod
riverpod copied to clipboard
Edge case of `Tried to read AutoDisposeProvider from a place where one of its dependencies were overridden but the provider is not.`
Describe the bug 2.0.0-dev.9
An edge case that triggers assertion failure:
The following assertion was thrown building Home(dirty, dependencies: [UncontrolledProviderScope],
state: _ConsumerState#53d0d):
Tried to read AutoDisposeProvider<int>#5dc5b(4) from a place where one of its dependencies were
overridden but the provider is not.
To fix this error, you can add add "dependencies" to AutoDisposeProvider<int>#5dc5b(4) such that we
have:
```
final a = Provider(...);
final b = Provider((ref) => ref.watch(a), dependencies: [a]);
```
'package:riverpod/src/framework/container.dart':
Failed assertion: line 492 pos 17: 'targetElement.provider != targetElement.origin ||
dependencyElement ==
targetElement.container
.readProviderElement<Object?>(dependency)'
Sample code:
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
void main() async {
runApp(
ProviderScope(
overrides: [
parentProvider.overrideWithProvider(
(arg) =>
StateNotifierProvider.autoDispose((ref) => StateController(arg)),
),
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ProviderScope(
// NOTE: override here will have no problem
/* overrides: [ */
/* parentProvider.overrideWithProvider( */
/* (arg) => StateNotifierProvider.autoDispose( */
/* (ref) => StateController(arg)), */
/* ), */
/* ], */
child: Home(),
),
);
}
}
class Home extends HookConsumerWidget {
const Home({
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
// NOTE: if you swap the call order of the following two `ref.watch`, then there will be no problem
ref.watch(parentProvider(4));
ref.watch(childProvider(4));
return const SizedBox();
}
}
// NOTE: seems like Provider has no problem
final parentProvider = StateNotifierProvider.autoDispose
.family<StateController<int>, int, int>((ref, arg) {
return StateController(0);
});
final childProvider = Provider.autoDispose.family((ref, int arg) {
return ref.watch(parentProvider(arg));
}, dependencies: [parentProvider]);
To Reproduce
Run the following code and you should see the assertion failure.
Expected behavior No failure.
The above code is the minimum code I can reproduce.
The problem in our production code seems more complex and can not be solved.
We have also to override the provider like childProvider in the sample code.
I am not sure if there is a relationship between the bug inside the sample code and the problem in our production code.
Hello!
I've tried your example on the master branch and failed to reproduce the issue. Either it was fixed implicitly or there's something else going on.
Do you mind maybe trying the master branch?
Hello
Yes, the sample code works well when using the master branch code.
It will take some time to confirm with our production code, since there seem like some breaking changes, e.g. overrideWithValue.
Closing as that was fixed