flutter runtime_error ai_generated true

StateError: Bad state: Cannot add event while adding another event

ID: flutter/state-error-bloc-event-handler

Also available as: JSON · Markdown · 中文
88%Fix Rate
88%Confidence
1Evidence
2023-11-15First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
flutter 3.16 active
flutter 3.22 active
bloc 8.0.0 active
flutter_bloc 8.1.0 active

Root Cause

Attempting to call bloc.add() from within an event handler of the same Bloc instance, causing a reentrant call.

generic

中文

在同一个 Bloc 实例的事件处理程序中调用 bloc.add(),导致重入调用。

Official Documentation

https://bloclibrary.dev/#/coreconcepts?id=adding-events

Workarounds

  1. 90% success Use a separate isolate or schedule the new event outside the current handler using Future.microtask(() => bloc.add(Event())). This ensures the current event processing completes before the new event is added.
    Use a separate isolate or schedule the new event outside the current handler using Future.microtask(() => bloc.add(Event())). This ensures the current event processing completes before the new event is added.
  2. 85% success Restructure the Bloc logic to combine both operations into a single event or use async gaps like await Future.delayed(Duration.zero) before calling bloc.add().
    Restructure the Bloc logic to combine both operations into a single event or use async gaps like await Future.delayed(Duration.zero) before calling bloc.add().

中文步骤

  1. 使用单独的隔离或通过 Future.microtask(() => bloc.add(Event())) 在当前处理程序外部调度新事件。这确保当前事件处理完成后再添加新事件。
  2. 重构 Bloc 逻辑,将两个操作合并为一个事件,或在使用 bloc.add() 之前使用异步间隙,如 await Future.delayed(Duration.zero)。

Dead Ends

Common approaches that don't work:

  1. Adding a short delay with Future.delayed before bloc.add() 85% fail

    Delay does not prevent the reentrant call from the same synchronous context; the error still occurs if the logic is in the same event handler chain.

  2. Wrapping bloc.add() in a try-catch block 75% fail

    The StateError is thrown synchronously and cannot be caught inside the event handler because Bloc internally throws it before the catch block is reached.