{"record":{"id":"f3e63a9f640a0020","repo":"microsoft/autogen","slug":"payload-is-null","errorCode":null,"errorMessage":"Payload is null.","messagePattern":"Payload is null\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Microsoft.AutoGen/Core.Grpc/GrpcAgentRuntime.cs","lineNumber":150,"sourceCode":"\n    private readonly bool _strictMessageDeserialization;\n    public IProtoSerializationRegistry SerializationRegistry { get; } = new ProtobufSerializationRegistry();\n\n    public void Dispose()\n    {\n        this._shutdownCts.Cancel();\n        this._messageRouter.Dispose();\n    }\n\n    private async ValueTask HandleRequest(RpcRequest request, CancellationToken cancellationToken = default)\n    {\n        if (request is null)\n        {\n            throw new InvalidOperationException(\"Request is null.\");\n        }\n        if (request.Payload is null)\n        {\n            throw new InvalidOperationException(\"Payload is null.\");\n        }\n        if (request.Target is null)\n        {\n            throw new InvalidOperationException(\"Target is null.\");\n        }\n\n        var agentId = request.Target;\n        var agent = await this._agentsContainer.EnsureAgentAsync(agentId.FromProtobuf());\n\n        // Convert payload back to object\n        var payload = request.Payload;\n        var message = payload.ToObject(SerializationRegistry);\n\n        var messageContext = new MessageContext(request.RequestId, cancellationToken)\n        {\n\n            Sender = request.Source?.FromProtobuf() ?? null,\n            Topic = null,","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/src/Microsoft.AutoGen/Core.Grpc/GrpcAgentRuntime.cs#L132-L168","documentation":"GrpcAgentRuntime.HandleRequest throws InvalidOperationException when an incoming RpcRequest carries a null Payload. Even with a valid Target, a request without a payload cannot be deserialized to a message, so the handler rejects it before agent resolution.","triggerScenarios":"RpcRequest arrives with Target set but Payload unset — a client that sends an invocation without serializing a message body, a proto where payload was dropped (optional field omitted), or a hand-built request in tests.","commonSituations":"SendMessage paths that serialize to the wrong registry and silently produce an empty payload; partial construction of RpcRequest after a refactor; interop with non-.NET clients that do not populate payload; version differences making Payload optional.","solutions":["Verify the sender sets Payload via the serialization registry before dispatching (check SendRequest construction).","Align serialization registries/proto versions between sender and receiver so payloads are populated.","If the message intentionally has no body, send an explicit empty-but-present payload type the receiver understands."],"exampleFix":"// before\nvar req = new RpcRequest { Target = target.ToProtobuf(), RequestId = rid }; // no Payload\n\n// after\nvar req = new RpcRequest\n{\n    Target = target.ToProtobuf(),\n    RequestId = rid,\n    Payload = message.ToProtobuf(serializationRegistry),\n};","handlingStrategy":"validation","validationCode":"if (request?.Payload is null)\n{\n    // reject at the send site instead: always serialize the message body before dispatch\n}","typeGuard":"static bool HasPayload(RpcRequest? r) => r?.Payload is not null;","tryCatchPattern":null,"preventionTips":["Always build RpcRequest with Payload = message.ToProtobuf(registry) at the send site.","Route body-less notifications through the publish path, not the request path."],"tags":["grpc","wire-protocol","payload","validation"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}