microsoft/autogen · error · InvalidOperationException
Message must have a receiver to be sent.
Error message
Message must have a receiver to be sent.
What it means
InProcessRuntime.SendMessageServicer is the callback invoked for point-to-point message deliveries. Before dispatching, it requires the MessageEnvelope to carry a Receiver (an AgentId); a delivery without one is a programming error because there is no agent to hand the message to. The guard throws InvalidOperationException as soon as the servicer runs, i.e. when the queued delivery is processed, not when it is enqueued.
Source
Thrown at dotnet/src/Microsoft.AutoGen/Core/InProcessRuntime.cs:106
public ValueTask PublishMessageAsync(object message, TopicId topic, AgentId? sender = null, string? messageId = null, CancellationToken cancellation = default)
{
return this.ExecuteTracedAsync(() =>
{
MessageDelivery delivery = new MessageEnvelope(message, messageId, cancellation)
.WithSender(sender)
.ForPublish(topic, this.PublishMessageServicer);
this.messageDeliveryQueue.Enqueue(delivery);
return delivery.FutureNoResult;
});
}
private async ValueTask<object?> SendMessageServicer(MessageEnvelope envelope, CancellationToken deliveryToken)
{
if (!envelope.Receiver.HasValue)
{
throw new InvalidOperationException("Message must have a receiver to be sent.");
}
CancellationTokenSource combinedSource = CancellationTokenSource.CreateLinkedTokenSource(envelope.Cancellation, deliveryToken);
MessageContext messageContext = new(envelope.MessageId, combinedSource.Token)
{
Sender = envelope.Sender,
IsRpc = false
};
AgentId receiver = envelope.Receiver.Value;
IHostableAgent agent = await this.EnsureAgentAsync(receiver);
return await agent.OnMessageAsync(envelope.Message, messageContext);
}
public ValueTask<object?> SendMessageAsync(object message, AgentId recepient, AgentId? sender = null, string? messageId = null, CancellationToken cancellationToken = default)
{
return this.ExecuteTracedAsync(async () =>View on GitHub (pinned to 027ecf0a37)
Solutions
- Set the receiver before enqueueing: build the envelope with .WithReceiver(agentId) (or use ForSend rather than ForPublish).
- Prefer the public SendMessageAsync(agent, message) API, which sets the receiver for you, instead of hand-building envelopes.
- Audit custom MessageEnvelope construction sites for missing WithReceiver calls.
Example fix
// before
MessageDelivery delivery = new MessageEnvelope(message, messageId, ct)
.WithSender(sender)
.ForPublish(topic, this.PublishMessageServicer);
await delivery.Future; // routed to SendMessageServicer without a receiver
// after
MessageDelivery delivery = new MessageEnvelope(message, messageId, ct)
.WithSender(sender)
.ForSend(receiver, this.SendMessageServicer);
await delivery.Future; Defensive patterns
Strategy: validation
Validate before calling
if (envelope.Receiver is not { } target)
{
throw new InvalidOperationException("Cannot send: envelope has no receiver.");
}
await runtime.SendMessageAsync(target, envelope.Message); Type guard
static bool HasReceiver(MessageEnvelope envelope) => envelope.Receiver.HasValue;
Try / catch
try { await runtime.SendMessageAsync(agentId, message); }
catch (InvalidOperationException ex) when (ex.Message.Contains("receiver")) { /* fix envelope construction; do not retry */ } Prevention
- Never hand-build MessageEnvelope for sends — use SendMessageAsync(agentId, message) or AgentProxy which set the receiver
- Keep ForPublish for topics and ForSend for point-to-point; never mix the two on one delivery
- Add a debug assertion on envelope.Receiver.HasValue before enqueueing custom deliveries
When it happens
Trigger: Enqueuing a MessageEnvelope that was built with ForPublish (which sets a topic, not a receiver) but serviced through the send path; constructing a MessageEnvelope manually and forgetting .WithReceiver(agentId); calling AgentProxy methods where the proxy was created from an envelope without a receiver. The check at InProcessRuntime.cs:106 is `if (!envelope.Receiver.HasValue)`.
Common situations: Mixing the publish API (PublishMessageAsync + ForPublish) with the send servicer; copy-pasting envelope-building code from a publish flow into a send flow; a custom MessageDelivery pipeline dropping the receiver assignment.
Related errors
- Unhandled message in group chat manager: {type(message)}
- Unhandled message in agent container: {type(message)}
- One or more exceptions occurred while processing the message
- Agent with name {agentId.Type} not found.
- Agent is already bound to a different runtime
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/ceffadecf51ed6c4.
Report an issue: GitHub.