microsoft/autogen · error · ArgumentException

Invalid message type

Error message

Invalid message type

What it means

SemanticKernelAgent.BuildChatHistory calls ProcessMessage, which pattern-matches each IMessage against IMessage<ChatMessageContent> only. Anything else — TextMessage, ImageMessage, MessageEnvelope of another type, plain Message — throws ArgumentException with 'Invalid message type'.

Source

Thrown at dotnet/src/AutoGen.SemanticKernel/SemanticKernelAgent.cs:134

            MaxTokens = options?.MaxToken ?? 1024,
            StopSequences = options?.StopSequence,
            ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
        };
    }

    private IChatCompletionService GetChatCompletionService()
    {
        return string.IsNullOrEmpty(_modelServiceId)
            ? _kernel.GetRequiredService<IChatCompletionService>()
            : _kernel.GetRequiredService<IChatCompletionService>(_modelServiceId);
    }

    private IEnumerable<ChatMessageContent> ProcessMessage(IEnumerable<IMessage> messages)
    {
        return messages.Select(m => m switch
        {
            IMessage<ChatMessageContent> cmc => cmc.Content,
            _ => throw new ArgumentException("Invalid message type")
        });
    }
}

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Wrap every message in MessageEnvelope<ChatMessageContent>, e.g. new MessageEnvelope<ChatMessageContent>(new ChatMessageContent(AuthorRole.User, text))
  2. Use the provided SemanticKernelChatMessageContentConnector middleware, which converts TextMessage and other common types into ChatMessageContent before the agent sees them
  3. Check each message with 'is IMessage<ChatMessageContent>' before sending and convert the ones that fail

Example fix

// before
var messages = new List<IMessage> { new TextMessage(Role.User, "hello") };
await skAgent.GenerateReplyAsync(messages);

// after
var messages = new List<IMessage>
{
    new MessageEnvelope<ChatMessageContent>(new ChatMessageContent(AuthorRole.User, "hello"))
};
await skAgent.GenerateReplyAsync(messages);
Defensive patterns

Strategy: type-guard

Validate before calling

var invalid = messages.Where(m => m is not IMessage<ChatMessageContent>).ToList();
if (invalid.Count > 0)
    throw new InvalidOperationException($"Non-ChatMessageContent messages: {string.Join(",", invalid.Select(m => m.GetType().Name))}");

Type guard

static IMessage<ChatMessageContent>? AsChatMessageContent(IMessage m) => m as IMessage<ChatMessageContent>;

// usage: messages.Select(AsChatMessageContent).Where(m => m is not null)

Try / catch

try { await skAgent.GenerateReplyAsync(messages); }
catch (ArgumentException ex) when (ex.Message == "Invalid message type")
{
    var converted = messages.Select(m => new MessageEnvelope<ChatMessageContent>(
        new ChatMessageContent(AuthorRole.User, m.GetContent()?.ToString() ?? string.Empty)));
    await skAgent.GenerateReplyAsync(converted); // fallback conversion retry
}

Prevention

When it happens

Trigger: Passing TextMessage/IMessage<TextContent>, ImageMessage, or any non-ChatMessageContent envelope to SemanticKernelAgent.GenerateReplyAsync/GenerateStreamingReplyAsync.

Common situations: Mixing messages produced by AutoGen core agents (which emit TextMessage) with a SemanticKernel agent, or building chat history manually with the convenience TextMessage type instead of wrapping ChatMessageContent.

Related errors


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