{"record":{"id":"ceffadecf51ed6c4","repo":"microsoft/autogen","slug":"message-must-have-a-receiver-to-be-sent","errorCode":null,"errorMessage":"Message must have a receiver to be sent.","messagePattern":"Message must have a receiver to be sent\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Microsoft.AutoGen/Core/InProcessRuntime.cs","lineNumber":106,"sourceCode":"    public ValueTask PublishMessageAsync(object message, TopicId topic, AgentId? sender = null, string? messageId = null, CancellationToken cancellation = default)\n    {\n        return this.ExecuteTracedAsync(() =>\n        {\n            MessageDelivery delivery = new MessageEnvelope(message, messageId, cancellation)\n                                        .WithSender(sender)\n                                        .ForPublish(topic, this.PublishMessageServicer);\n\n            this.messageDeliveryQueue.Enqueue(delivery);\n\n            return delivery.FutureNoResult;\n        });\n    }\n\n    private async ValueTask<object?> SendMessageServicer(MessageEnvelope envelope, CancellationToken deliveryToken)\n    {\n        if (!envelope.Receiver.HasValue)\n        {\n            throw new InvalidOperationException(\"Message must have a receiver to be sent.\");\n        }\n\n        CancellationTokenSource combinedSource = CancellationTokenSource.CreateLinkedTokenSource(envelope.Cancellation, deliveryToken);\n        MessageContext messageContext = new(envelope.MessageId, combinedSource.Token)\n        {\n            Sender = envelope.Sender,\n            IsRpc = false\n        };\n\n        AgentId receiver = envelope.Receiver.Value;\n        IHostableAgent agent = await this.EnsureAgentAsync(receiver);\n\n        return await agent.OnMessageAsync(envelope.Message, messageContext);\n    }\n\n    public ValueTask<object?> SendMessageAsync(object message, AgentId recepient, AgentId? sender = null, string? messageId = null, CancellationToken cancellationToken = default)\n    {\n        return this.ExecuteTracedAsync(async () =>","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/src/Microsoft.AutoGen/Core/InProcessRuntime.cs#L88-L124","documentation":"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.","triggerScenarios":"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)`.","commonSituations":"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.","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."],"exampleFix":"// before\nMessageDelivery delivery = new MessageEnvelope(message, messageId, ct)\n    .WithSender(sender)\n    .ForPublish(topic, this.PublishMessageServicer);\nawait delivery.Future; // routed to SendMessageServicer without a receiver\n\n// after\nMessageDelivery delivery = new MessageEnvelope(message, messageId, ct)\n    .WithSender(sender)\n    .ForSend(receiver, this.SendMessageServicer);\nawait delivery.Future;","handlingStrategy":"validation","validationCode":"if (envelope.Receiver is not { } target)\n{\n    throw new InvalidOperationException(\"Cannot send: envelope has no receiver.\");\n}\nawait runtime.SendMessageAsync(target, envelope.Message);","typeGuard":"static bool HasReceiver(MessageEnvelope envelope) => envelope.Receiver.HasValue;","tryCatchPattern":"try { await runtime.SendMessageAsync(agentId, message); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"receiver\")) { /* fix envelope construction; do not retry */ }","preventionTips":["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"],"tags":["csharp","runtime","message-routing","api-misuse"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}