microsoft/autogen · error · InvalidOperationException
Unexpected message '{message}'.
Error message
Unexpected message '{message}'. What it means
Thrown in OnMessageAsync when the Message oneof case is none of Request, Response, or CloudEvent — most commonly MessageOneofCase.None (an unset message) or a case added in a newer protocol version. The runtime treats any unrecognized shape as a protocol violation.
Source
Thrown at dotnet/src/Microsoft.AutoGen/Core.Grpc/GrpcAgentRuntime.cs:487
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
- Ensure every Message sent has exactly one of Request, Response, or CloudEvent set
- Align client SDK and runtime versions so both sides understand the same oneof cases
- Add a guard before dispatch: skip/log messages with MessageCase == MessageOneofCase.None
Example fix
// before
await router.SendAsync(new Message()); // empty -> throws
// after
if (msg.MessageCase == Message.MessageOneofCase.None) { /* skip */ }
else { await runtime.OnMessageAsync(msg); } Defensive patterns
Strategy: validation
Validate before calling
if (msg.MessageCase is not (Message.MessageOneofCase.Request or Message.MessageOneofCase.Response or Message.MessageOneofCase.CloudEvent))
{
_logger.LogWarning("Dropping unsupported message case {Case}", msg.MessageCase);
return;
} Type guard
static bool IsSupported(Message m) => m.MessageCase is Message.MessageOneofCase.Request or Message.MessageOneofCase.Response or Message.MessageOneofCase.CloudEvent;
Try / catch
try { await runtime.OnMessageAsync(msg); } catch (InvalidOperationException ex) when (ex.Message.Contains("Unexpected message")) { _logger.LogWarning(ex, "Unsupported message case"); } Prevention
- Filter MessageCase.None and unknown cases before dispatch
- Pin matching SDK/runtime versions to avoid unrecognized oneof cases
When it happens
Trigger: Sending new Message() with no oneof field set; sending a message whose oneof case exists only in a newer proto (e.g. a new message kind) to an older runtime; deserialization errors that leave the oneof unset.
Common situations: Version skew between client SDK and runtime (new message kinds not understood by the old side); accidental dispatch of empty messages; fire-and-forget code paths that construct Message without payload.
Related errors
- Response is null.
- Invalid subscription type
- Invalid subscription message.
- Unknown attribute kind
- Agent with name {agentId.Type} not found.
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/b19abd1b8defdc50.
Report an issue: GitHub.