{"record":{"id":"6be71e6d109beec5","repo":"microsoft/semantic-kernel","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/Agents/Runtime/InProcess/InProcessRuntime.cs","lineNumber":401,"sourceCode":"            };\n\n            AgentId agentId = subscription.MapToAgent(topic);\n            if (!this.DeliverToSelf && sender.HasValue && sender == agentId)\n            {\n                return;\n            }\n\n            IHostableAgent agent = await this.EnsureAgentAsync(agentId).ConfigureAwait(false);\n\n            await agent.OnMessageAsync(envelope.Message, messageContext).ConfigureAwait(false);\n        }\n    }\n\n    private async ValueTask<object?> SendMessageServicerAsync(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        using 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).ConfigureAwait(false);\n\n        return await agent.OnMessageAsync(envelope.Message, messageContext).ConfigureAwait(false);\n    }\n\n    private async ValueTask<IHostableAgent> EnsureAgentAsync(AgentId agentId)\n    {\n        if (!this.agentInstances.TryGetValue(agentId, out IHostableAgent? agent))","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Agents/Runtime/InProcess/InProcessRuntime.cs#L383-L419","documentation":"SendMessageServicerAsync (the internal servicer wired by ForSend) throws InvalidOperationException if envelope.Receiver has no value. The public SendMessageAsync always sets the recipient via ForSend, so this throw indicates a MessageEnvelope was routed through the send servicer without a receiver — i.e. internal/custom misuse rather than normal API usage.","triggerScenarios":"Constructing a MessageEnvelope and wiring ForSend without a receiver; a custom servicer reusing SendMessageServicerAsync on a publish envelope; envelope mutation that clears the receiver before servicing.","commonSituations":"Extending the runtime and mis-wiring servicers; custom delivery plumbing bugs; passing null recipient through internal paths.","solutions":["Always send via the public SendMessageAsync(message, recipient, ...) which guarantees the receiver is set.","When building a MessageEnvelope manually for send, always provide a recipient AgentId to ForSend.","Keep publish and send servicers/servicing paths separate."],"exampleFix":"// before (custom plumbing)\nvar env = new MessageEnvelope(msg, id, ct);\nenv.ForSend(recipient: null, sendServicer); // receiver never set\n\n// after\nawait runtime.SendMessageAsync(msg, new AgentId(\"worker\", \"1\"));","handlingStrategy":"validation","validationCode":"// Always send through the public API which sets the receiver.\nawait runtime.SendMessageAsync(message, new AgentId(\"worker\", \"1\"));\n// If building an envelope manually, ensure a recipient AgentId is supplied to ForSend.","typeGuard":"bool HasReceiver(MessageEnvelope env) => env.Receiver.HasValue;","tryCatchPattern":null,"preventionTips":["Use SendMessageAsync rather than wiring servicers manually.","Never route a publish-oriented envelope through the send servicer.","When extending the runtime, preserve the receiver through to the servicer."],"tags":["inprocess-runtime","messaging","send","receiver","dotnet"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}