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

  1. Register the connector: agent = new OpenAIChatAgent(...).RegisterMessageConnector();
  2. Or pre-convert messages to MessageEnvelope<ChatRequestMessage> before sending
  3. 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

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


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