microsoft/autogen · error · InvalidOperationException

Response is null.

Error message

Response is null.

What it means

Thrown in OnMessageAsync when the Message oneof case is Response but message.Response is null. As with other oneof guards, protobuf normally keeps the case and payload consistent, so this fires only when the message was constructed or mutated abnormally (reflection, partial parse, or nulling the field after the case was set).

Source

Thrown at dotnet/src/Microsoft.AutoGen/Core.Grpc/GrpcAgentRuntime.cs:479

        Dictionary<string, JsonElement> state = new();
        foreach (var agent in this._agentsContainer.LiveAgents)
        {
            var agentState = await agent.SaveStateAsync();
            state[agent.Id.ToString()] = JsonSerializer.SerializeToElement(agentState);
        }
        return JsonSerializer.SerializeToElement(state);
    }

    public async ValueTask OnMessageAsync(Message message, CancellationToken cancellation = default)
    {
        switch (message.MessageCase)
        {
            case Message.MessageOneofCase.Request:
                var request = message.Request ?? throw new InvalidOperationException("Request is null.");
                await HandleRequest(request);
                break;
            case Message.MessageOneofCase.Response:
                var response = message.Response ?? throw new InvalidOperationException("Response is null.");
                await HandleResponse(response);
                break;
            case Message.MessageOneofCase.CloudEvent:
                var cloudEvent = message.CloudEvent ?? throw new InvalidOperationException("CloudEvent is null.");
                await HandlePublish(cloudEvent);
                break;
            default:
                throw new InvalidOperationException($"Unexpected message '{message}'.");
        }
    }
}

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Assign a non-null Response when constructing the message: new Message { Response = response }
  2. Use ClearResponse() instead of Response = null when you need to unset the field
  3. Avoid reusing and mutating Message instances across requests; create a fresh Message per send

Example fix

// before
msg.Response = null; // case stays Response -> throws on next dispatch

// after
msg.ClearResponse();
Defensive patterns

Strategy: validation

Validate before calling

if (message.MessageCase == Message.MessageOneofCase.Response && message.Response is null) throw new InvalidOperationException("Malformed message");

Type guard

static bool HasResponsePayload(Message m) => m.MessageCase != Message.MessageOneofCase.Response || m.Response is not null;

Try / catch

try { await runtime.OnMessageAsync(msg); } catch (InvalidOperationException ex) when (ex.Message == "Response is null.") { _logger.LogWarning(ex, "Dropping malformed message"); }

Prevention

When it happens

Trigger: Setting message.Response = null after the oneof case was already set to Response; building Message via reflection without the payload; a peer sending a hand-crafted message with the response case set but no payload.

Common situations: Unit tests faking Message instances; client code mutating pooled/reused Message objects; proto schema drift between sender and receiver.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/749ed9549ac285ff. Report an issue: GitHub.