Skip to content

dispose_provided_instances

v0.4.0WarningFixConfigurableBloc / Riverpod

This rule flags instances created inside Riverpod provider callbacks or Notifier build() methods that have a dispose(), close(), or cancel() method but are not cleaned up via ref.onDispose(). It recognizes tear-off, lambda, and block body cleanup patterns.

When a provider creates a disposable resource (like a controller, stream subscription, or service with a close() method) without registering cleanup, the resource leaks when the provider is destroyed. This leads to memory leaks and resource exhaustion over time. The ref.onDispose() callback ensures proper cleanup regardless of how or when the provider is disposed.

See also: Riverpod automatic disposal

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod/riverpod.dart';
class DisposableService {
void dispose() {}
String get value => 'hello';
}
// Instance has dispose() but ref.onDispose is not called
final badProvider = Provider<DisposableService>((ref) {
final instance = DisposableService();
return instance;
});
// Notifier build() creates disposable without ref.onDispose
class BadNotifier extends Notifier<DisposableService> {
@override
DisposableService build() {
final instance = DisposableService();
return instance;
}
}
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod/riverpod.dart';
class DisposableService {
void dispose() {}
String get value => 'hello';
}
// Using ref.onDispose with tear-off
final goodProvider = Provider<DisposableService>((ref) {
final instance = DisposableService();
ref.onDispose(instance.dispose);
return instance;
});
// Using ref.onDispose with lambda
final goodLambdaProvider = Provider<DisposableService>((ref) {
final instance = DisposableService();
ref.onDispose(() => instance.dispose());
return instance;
});
// Notifier build() with ref.onDispose
class GoodNotifier extends Notifier<DisposableService> {
@override
DisposableService build() {
final instance = DisposableService();
ref.onDispose(instance.dispose);
return instance;
}
}

This rule is in the recommended preset, so it is on with preset: recommended or preset: opinionated. Add it to preset: core with dispose_provided_instances: true.

To turn it off:

many_lints.yaml
rules:
dispose_provided_instances: false

To keep the rule on but skip certain paths, use per-rule exclude.

analysis_options.yaml
many_lints:
rules:
dispose_provided_instances:
additional_cleanup_methods: [release, shutdown]
Option Type Default Description
cleanup_methods list of strings [dispose, close, cancel] Replaces the cleanup method names the rule looks for
additional_cleanup_methods list of strings [] Extends whichever list applies

Order matters: it is the priority used when a type declares more than one cleanup method. Names added via additional_cleanup_methods are appended, so a project’s own release() is only chosen when the type declares no standard cleanup method.

Both options apply to detection and recognition — a method listed here counts both as “this instance needs disposing” and as “this ref.onDispose disposes it”.