handle_bloc_event_subclasses
v1.0.0 Warning Bloc / Riverpod
This rule flags a Bloc whose sealed event hierarchy has a subclass with no on<E> handler. Adding an unregistered event does nothing at all at runtime.
Why use this rule
Section titled “Why use this rule”on<E> registration is a runtime lookup keyed by type. If no handler is registered for an event, add(MyEvent()) returns normally, emits no state, throws nothing and logs nothing. The feature simply does not work.
The gap almost always appears later: a new event class joins the hierarchy and the matching on<E> is forgotten. Because the compiler cannot see the omission, only a test that exercises that exact event will catch it — and the missing event is usually the one no test covers yet.
See also: bloc: Bloc.on
sealed class CounterEvent {}class Increment extends CounterEvent {}class Decrement extends CounterEvent {}
class CounterBloc extends Bloc<CounterEvent, int> { CounterBloc() : super(0) { on<Increment>((event, emit) => emit(state + 1)); // `Decrement` is never handled — adding it does nothing }}class CounterBloc extends Bloc<CounterEvent, int> { CounterBloc() : super(0) { on<Increment>((event, emit) => emit(state + 1)); on<Decrement>((event, emit) => emit(state - 1)); }}A handler for the base type covers every subclass:
on<CounterEvent>((event, emit) => emit(state));Known limitations
Section titled “Known limitations”Only sealed event hierarchies are checked. A sealed type may only be extended within its own library, so its subtypes are knowable. For an open base class a subtype may live in any library, so “every subtype” cannot be computed and a report would be guesswork — make the event base sealed to get this check, which is good practice regardless.
Handlers are found by scanning the class for on<E>(...) calls, so a registration made outside the Bloc, or through a helper, is not detected.
Configuration
Section titled “Configuration”This rule is in the recommended preset, so it is on with
preset: recommended or preset: opinionated. Add it to preset: core with
handle_bloc_event_subclasses: true.
To turn it off:
rules: handle_bloc_event_subclasses: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”avoid_duplicate_bloc_event_handlers— Register each bloc event type exactly once.emit_new_bloc_state_instances— Emit a new state instance instead of the existing state object.prefer_immutable_bloc_state— Ensure Bloc and Cubit state classes are annotated with @immutable.avoid_bloc_public_methods— Prevent public methods, getters, and setters in Bloc classes.