LOW SEVERITYCONFIRMED

_execute_single_listener exceptions swallowed by asyncio.gather — non-deterministic flow state

Package
crewai
Version
HEAD
Verified
2026-03-28

Description

crewai's `_execute_racing_and_other_listeners` calls `asyncio.gather(*other_tasks, return_exceptions=True)`, which silently discards exceptions from non-racing listeners. If a listener raises after partial side effects, `_completed_methods` is not updated and the flow continues as though that listener never ran. Given the same event and state, two runs can produce different `_completed_methods` sets depending on whether a transient error occurred.

Reproduction

# A Flow listener that raises on first call:
# Run 1: listener raises -> exception swallowed -> listener not in _completed_methods
# Run 2: listener succeeds -> listener in _completed_methods
# Same initial state, different outcomes — non-determinism under error conditions
← All bugsScan your code →