From 5f256e241cfaaddb98ebfbdf9c75dde73012ed12 Mon Sep 17 00:00:00 2001 From: filipi87 Date: Thu, 7 May 2026 11:29:57 -0300 Subject: [PATCH 1/2] Fixing a race condition when cleaning up the daily transport. --- src/pipecat/transports/daily/transport.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/pipecat/transports/daily/transport.py b/src/pipecat/transports/daily/transport.py index 2d30ceecb..c4c76c0b0 100644 --- a/src/pipecat/transports/daily/transport.py +++ b/src/pipecat/transports/daily/transport.py @@ -526,6 +526,7 @@ class DailyTransportClient(EventHandler): self._joined = False self._joined_event = asyncio.Event() self._leave_counter = 0 + self._cleanup_counter = 0 self._task_manager: BaseTaskManager | None = None @@ -741,6 +742,7 @@ class DailyTransportClient(EventHandler): Args: setup: The frame processor setup configuration. """ + self._cleanup_counter += 1 if self._task_manager: return @@ -754,6 +756,12 @@ class DailyTransportClient(EventHandler): async def cleanup(self): """Cleanup client resources and cancel tasks.""" + # Decrement cleanup counter. DailyInputTransport and DailyOutputTransport + # share this client and both call cleanup(), so only run on the last call. + self._cleanup_counter -= 1 + if self._cleanup_counter > 0: + return + if self._event_task and self._task_manager: await self._task_manager.cancel_task(self._event_task) self._event_task = None From f91a55c97c2787dc19406ba7cb5438e4b5a01c93 Mon Sep 17 00:00:00 2001 From: filipi87 Date: Thu, 7 May 2026 11:32:48 -0300 Subject: [PATCH 2/2] Changelog entry for the fix. --- changelog/4440.fixed.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/4440.fixed.md diff --git a/changelog/4440.fixed.md b/changelog/4440.fixed.md new file mode 100644 index 000000000..7be44d193 --- /dev/null +++ b/changelog/4440.fixed.md @@ -0,0 +1 @@ +- Fixed a race condition in the Daily transport that caused `AttributeError: 'NoneType' object has no attribute 'send_app_message'` when tearing down a pipeline. Both `DailyInputTransport` and `DailyOutputTransport` share the same `DailyTransportClient` and both call `cleanup()`, which was releasing the underlying `CallClient` on the first call — leaving the second caller with a `None` client.