microsoft/semantic-kernel · error · Exception

Unexpected failure broadcasting to channel: {type(channel_re

Error message

Unexpected failure broadcasting to channel: {type(channel_ref.channel)}, failure: {failure}

What it means

The broadcast loop drains each channel's QueueReference. If a prior receive() coroutine recorded a failure in queue_ref.receive_failure, that failure is surfaced on the next iteration by raising a new Exception chained with `from failure`. The actual error occurred asynchronously inside AgentChannel.receive; this raise is how the broadcasting caller learns about it.

Source

Thrown at python/semantic_kernel/agents/group_chat/broadcast_queue.py:94

    async def ensure_synchronized(self, channel_ref: ChannelReference) -> None:
        """Blocks until a channel-queue is not in a receive state to ensure that channel history is complete.

        Args:
            channel_ref: The channel reference.
        """
        if channel_ref.hash not in self.queues:
            return

        queue_ref = self.queues[channel_ref.hash]

        while True:
            async with queue_ref.queue_lock:
                is_empty = queue_ref.is_empty

                if queue_ref.receive_failure is not None:
                    failure = queue_ref.receive_failure
                    queue_ref.receive_failure = None
                    raise Exception(
                        f"Unexpected failure broadcasting to channel: {type(channel_ref.channel)}, failure: {failure}"
                    ) from failure

                if not is_empty and (not queue_ref.receive_task or queue_ref.receive_task.done()):
                    queue_ref.receive_task = asyncio.create_task(self.receive(channel_ref, queue_ref))

            if is_empty:
                break

            await asyncio.sleep(self.block_duration)

    async def receive(self, channel_ref: ChannelReference, queue_ref: QueueReference) -> None:
        """Processes the specified queue with the provided channel, until the queue is empty.

        Args:
            channel_ref: The channel reference.
            queue_ref: The queue reference.
        """

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Read exc.__cause__ (the original `failure`) to identify the real channel error rather than the broadcast wrapper.
  2. Inspect and fix the AgentChannel implementation whose receive() raised — add input validation and proper error handling inside receive.
  3. Ensure messages placed on the queue are types the channel can deserialize; verify channel compatibility with the broadcasting agent.
  4. Reproduce with logging inside receive() to capture the exact failing payload before it surfaces here.

Example fix

// before
class MyChannel(AgentChannel):
    async def receive(self, *args, **kwargs):
        return json.loads(self._raw)  # raises if _raw invalid -> surfaces as broadcast failure

// after
class MyChannel(AgentChannel):
    async def receive(self, *args, **kwargs):
        try:
            return json.loads(self._raw)
        except json.JSONDecodeError:
            logger.warning("dropping malformed channel payload")
            return None
Defensive patterns

Strategy: try-catch

Try / catch

try:
    await broadcaster.broadcast(message)
except Exception as e:
    cause = e.__cause__  # the original channel.receive failure
    logger.error("channel receive failed: %s", cause)

Prevention

When it happens

Trigger: AgentChannel.receive() raised while draining a broadcast queue. On the next broadcast iteration the stored receive_failure is non-None, so the loop raises this wrapped exception. Triggers include a buggy custom channel, a serialization/deserialization error in channel.receive, or a downstream transport failure.

Common situations: Custom AgentChannel subclass whose receive() throws on malformed input; a channel backed by a remote service that drops the connection mid-receive; incompatible message types reaching the channel; partial state after an earlier crash that left receive_failure set.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/6fe811da5cfcc97b. Report an issue: GitHub.