Skip to content

avoid_duplicate_bloc_event_handlers

v0.8.0WarningConfigurableBloc & Riverpod

This rule flags a bloc constructor that registers the same event type with on<E> more than once.

Bloc.on<E> asserts that each event type has exactly one handler. A second registration for the same type throws a StateError:

on<IncrementEvent> was called multiple times.

Because the registration happens in the constructor, the throw fires the first time the bloc is instantiated — often deep in a provider or a route builder, far from the duplicated line. Catching it at analysis time turns a runtime crash into a squiggle on the exact call.

The usual cause is a copy-pasted on<...> line where the type argument was not updated.

See also: bloc: Bloc.on

class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<IncrementEvent>((event, emit) => emit(state + 1));
// Throws at construction — the type argument was never updated
on<IncrementEvent>((event, emit) => emit(state - 1));
}
}
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<IncrementEvent>((event, emit) => emit(state + 1));
on<DecrementEvent>((event, emit) => emit(state - 1));
}
}

If two behaviours genuinely belong to one event, merge them into a single handler.

Registrations are tracked per constructor. A bloc with two constructors that each register the same event is not flagged, because only one of them runs for any given instance.

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

To turn it off:

many_lints.yaml
rules:
avoid_duplicate_bloc_event_handlers: false

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

analysis_options.yaml
many_lints:
rules:
avoid_duplicate_bloc_event_handlers:
additional_methods: [onEvent]
Option Type Default Description
additional_methods list of strings [] Extra registration methods treated like Bloc’s on, for a project wrapper that forwards to it