Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bad state: Tried to read a provider from a ProviderContainer that was already disposed #3661

Open
diasmalibekov opened this issue Jul 17, 2024 · 4 comments
Assignees
Labels
bug Something isn't working question Further information is requested

Comments

@diasmalibekov
Copy link

diasmalibekov commented Jul 17, 2024

Describe the bug
hi, it's me again
I think I found new trouble, I am still writing tests and my test calls two functions:

 Future<void> handleNewWSUrls(UserSipSettingsSaved newSipSettings) async {
    await clearFailedWSUrls();
    final activeWSUrl = await ref.read(**currentWSUrlProvider**.future);
    print('current ws url - $activeWSUrl');

    if (activeWSUrl is! ActiveWSUrlSaved ||
        !newSipSettings.sip.webrtcUrls.contains(activeWSUrl.wsUrl)) {
      await calculateActiveWSUrl(newSipSettings);
    }
  }
  /// Calculates active ws url
  Future<void> calculateActiveWSUrl(UserSipSettings sipSettings) async {
    state = const AsyncLoading();

    if (sipSettings is! UserSipSettingsSaved) {
      state = AsyncValue.error(const ActiveWSUrlsError(), StackTrace.current);

      return;
    }

    final blockedWSUrls =
        await ref.read(failedWSUrlsStorageDataSourceImplProvider).read();
    final availableWSUrls = sipSettings.sip.webrtcUrls
        .where((url) => !blockedWSUrls.urls.contains(url))
        .toList();

    if (availableWSUrls.isEmpty) {
      state = AsyncValue.error(const ActiveWSUrlsError(), StackTrace.current);

      return;
    }

    print('new url - ${availableWSUrls.first}');

    await ref
        .read(**currentWSUrlProvider**.notifier)
        .setActiveUrl(ActiveWSUrl.saved(wsUrl: availableWSUrls.first));

    print('active ws url updated');
    ref.invalidateSelf();
    await future;
  }

so, despite in my tests I listen to currentWSUrlProvider like this:
container.listen(currentWSUrlProvider, (_, __) {});
right after this line

state = const AsyncLoading();

in calculateActiveWSUrl function - currentWSUrlProvider disposed and I see such an error
when try to read

 await ref
        .read(**currentWSUrlProvider**.notifier)
        .setActiveUrl(ActiveWSUrl.saved(wsUrl: availableWSUrls.first));

in calculateActiveWSUrl function
Bad state: Tried to read a provider from a ProviderContainer that was already disposed
this is my currentWSUrlProvider

 class CurrentWSUrl extends _$CurrentWSUrl {
  @override
  Future<ActiveWSUrl> build() async {
    ref.onDispose(() => print('bye everyone'));
    ref.onAddListener(() => print('new listener'));
    ref.onRemoveListener(() => print('remove listener'));
    final wsUrl =
        await ref.watch(activeWSUrlStorageDataSourceImplProvider).read();
    return wsUrl;
  }
}

and I see such logs also, so I assume that provider still has at least one listener:
new listener
new listener
current ws url - ActiveWSUrl.saved(wsUrl: mock_ws_url)
bye everyone
new url - mockWebrtcUrl1
Bad state: Tried to read a provider from a ProviderContainer that was already disposed

Expected behavior
Expected that provider will keep alive until it has at least one listener

@snapsl
Copy link

snapsl commented Jul 17, 2024

Hi , again share a minimal reproducible example.

@diasmalibekov
Copy link
Author

Ok, I'll try to provide you simplified version of the code that causes this error

@rrousselGit rrousselGit added question Further information is requested and removed needs triage labels Jul 22, 2024
@diasmalibekov
Copy link
Author

diasmalibekov commented Jul 22, 2024

you can reproduce this error with the next code:
file provider1.dart

import provider2Provider;
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'provider1.g.dart';

@riverpod
class Provider1 extends _$Provider1 {
  @override
  Future<int> build() async {
    await ref.watch(provider2Provider.future);
    return Future.value(1);
  }

  void callSecond() {
    print('calling second provider');
    ref.read(provider2Provider.notifier).sayHello();
  }

  void printSum() async {
    final sum = (await ref.read(provider2Provider.future)) + (await future);
    print('sum is - $sum');
    callSecond();
  }
}

file provider2.dart

import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'provider2.g.dart';

@riverpod
class Provider2 extends _$Provider2 {
  @override
  Future<int> build() async {
    ref
      ..onAddListener(() => print('+ listener'))
      ..onRemoveListener(() => print('- listener'))
      ..onDispose(() => print('bye'));

    return Future.value(2);
  }

  void sayHello() => print('provider 2');
}

test file:

import 'package:flutter_test/flutter_test.dart';
import provider1Provider, provider2Provider;
import 'package:riverpod/riverpod.dart';

import '../../../../helpers/helpers.dart';

void main() {
  group('Provider1', () {
    late ProviderContainer providerContainer;
    setUp(() {
      providerContainer = createContainer();
    });
    test('test calling notifier method', () async {
      final sub =
          providerContainer.listen(provider1Provider.future, (_, __) {});
      final sub2 =
          providerContainer.listen(provider2Provider.future, (_, __) {});

      await sub.read();
      await sub2.read();
      providerContainer.read(provider1Provider.notifier).printSum();
    });
  });
}

@rrousselGit rrousselGit removed the question Further information is requested label Jul 22, 2024
@rrousselGit
Copy link
Owner

Your printSum is async but unawaited

+  Future<void> printSum() async {
    final sum = (await ref.read(provider2Provider.future)) + (await future);
    print('sum is - $sum');
    callSecond();
  }

....

+      await providerContainer.read(provider1Provider.notifier).printSum();

@rrousselGit rrousselGit added the question Further information is requested label Jul 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants