microsoft/autogen · error · ArgumentException
Invalid message type
Error message
Invalid message type
What it means
CreateChatCompletionsOptions maps each incoming IMessage to a ChatRequestMessage and throws ArgumentException when a message is not IMessage<ChatRequestMessage>. OpenAIChatAgent's core path expects messages already converted to OpenAI SDK request types (normally done by the RegisterMessageConnector middleware).
Source
Thrown at dotnet/src/AutoGen.OpenAI.V1/Agent/OpenAIChatAgent.cs:129
var settings = this.CreateChatCompletionsOptions(options, messages);
var response = await this.openAIClient.GetChatCompletionsStreamingAsync(settings, cancellationToken);
await foreach (var update in response.WithCancellation(cancellationToken))
{
if (update.ChoiceIndex > 0)
{
throw new InvalidOperationException("Only one choice is supported in streaming response");
}
yield return new MessageEnvelope<StreamingChatCompletionsUpdate>(update, from: this.Name);
}
}
private ChatCompletionsOptions CreateChatCompletionsOptions(GenerateReplyOptions? options, IEnumerable<IMessage> messages)
{
var oaiMessages = messages.Select(m => m switch
{
IMessage<ChatRequestMessage> chatRequestMessage => chatRequestMessage.Content,
_ => throw new ArgumentException("Invalid message type")
});
// add system message if there's no system message in messages
if (!oaiMessages.Any(m => m is ChatRequestSystemMessage))
{
oaiMessages = new[] { new ChatRequestSystemMessage(systemMessage) }.Concat(oaiMessages);
}
// clone the options by serializing and deserializing
var json = JsonSerializer.Serialize(this.options);
var settings = JsonSerializer.Deserialize<ChatCompletionsOptions>(json) ?? throw new InvalidOperationException("Failed to clone options");
foreach (var m in oaiMessages)
{
settings.Messages.Add(m);
}
settings.Temperature = options?.Temperature ?? settings.Temperature;View on GitHub (pinned to 027ecf0a37)
Solutions
- Register the connector: agent = new OpenAIChatAgent(...).RegisterMessageConnector();
- Or pre-convert messages to MessageEnvelope<ChatRequestMessage> before sending
- Prefer the higher-level GPTAgent or the documented builder that wires the connector for you
Example fix
// before
var agent = new OpenAIChatAgent(client, "gpt", options);
await agent.SendAsync(new TextMessage(Role.User, "hi")); // throws
// after
var agent = new OpenAIChatAgent(client, "gpt", options)
.RegisterMessageConnector();
await agent.SendAsync(new TextMessage(Role.User, "hi")); Defensive patterns
Strategy: validation
Validate before calling
bool allConvertible = messages.All(m => m is IMessage<ChatRequestMessage>); if (!allConvertible) agent = agent.RegisterMessageConnector();
Type guard
static bool IsChatRequestEnvelope(IMessage m) => m is IMessage<ChatRequestMessage>;
Try / catch
catch (ArgumentException ex) when (ex.Message == "Invalid message type")
{
var wired = agent.RegisterMessageConnector();
return await wired.SendAsync(messages);
} Prevention
- Always chain .RegisterMessageConnector() on OpenAIChatAgent
- Prefer GPTAgent which wires the connector
- Standardize on one agent construction helper across the codebase
When it happens
Trigger: Calling GenerateReplyAsync/GenerateStreamingReplyAsync on a bare OpenAIChatAgent (without .RegisterMessageConnector()) with TextMessage, ImageMessage, or any AutoGen primitive message type.
Common situations: Using the low-level agent directly instead of the extension-method chain; forgetting that GPTAgent and the documentation's agent setup attach the connector implicitly; custom pipelines that skip middleware registration.
Related errors
- Invalid return message type {message.GetType().Name}
- Unexpected message type: {message?.GetType()}
- Unknown message type: {m.GetType()}
- Unknown message type: {message.GetType()}
- Invalid streaming message type {reply.GetType().Name}
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/64bf64726b2478f3.
Report an issue: GitHub.