microsoft/autogen · error · ArgumentException

The first message must be from the user or function

Error message

The first message must be from the user or function

What it means

Thrown by GeminiChatAgent.BuildChatRequest because the Gemini multi-turn chat API requires the conversation to start with a 'user' (or 'function') role message. If the first converted Content has any other role (typically 'model'/assistant, or a system message first), ArgumentException is thrown with paramName 'messages'.

Source

Thrown at dotnet/src/AutoGen.Gemini/GeminiChatAgent.cs:173

    }

    private GenerateContentRequest BuildChatRequest(IEnumerable<IMessage> messages, GenerateReplyOptions? options)
    {
        var geminiMessages = messages.Select(m => m switch
        {
            IMessage<Content> contentMessage => contentMessage.Content,
            _ => throw new NotSupportedException($"Message type {m.GetType()} is not supported.")
        });

        // there are several rules applies to the messages that can be sent to Gemini in a multi-turn chat
        // - The first message must be from the user or function
        // - The (user|model) roles must alternate e.g. (user, model, user, model, ...)
        // - The last message must be from the user or function

        // check if the first message is from the user
        if (geminiMessages.FirstOrDefault()?.Role != "user" && geminiMessages.FirstOrDefault()?.Role != "function")
        {
            throw new ArgumentException("The first message must be from the user or function", nameof(messages));
        }

        // check if the last message is from the user
        if (geminiMessages.LastOrDefault()?.Role != "user" && geminiMessages.LastOrDefault()?.Role != "function")
        {
            throw new ArgumentException("The last message must be from the user or function", nameof(messages));
        }

        // merge continuous messages with the same role into one message
        var mergedMessages = geminiMessages.Aggregate(new List<Content>(), (acc, message) =>
        {
            if (acc.Count == 0 || acc.Last().Role != message.Role)
            {
                acc.Add(message);
            }
            else
            {
                acc.Last().Parts.AddRange(message.Parts);

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Reorder messages so the first message has role "user" (prepend a user message like "continue" if needed)
  2. Drop or convert leading assistant/system messages before sending (system content can often be merged into the first user turn)
  3. Use GeminiMessageConnector plus consistent chat history construction from the library's chat abstractions, which maintain the ordering

Example fix

// before:
var messages = new List<IMessage> { assistantReply, userMsg }; // first is model role -> throws
// after:
var messages = new List<IMessage> { userMsg, assistantReply, userMsg2 }; // starts with user
Defensive patterns

Strategy: validation

Validate before calling

// Enforce Gemini ordering before the call
var first = messages.FirstOrDefault() as IMessage<Content>;
if (first?.Content.Role is not ("user" or "function"))
    messages = new[] { new TextMessage(Role.User, "continue") }.Concat(messages);

Type guard

static bool StartsAfterUserTurn(IEnumerable<IMessage> msgs) =>
    (msgs.FirstOrDefault() as IMessage<Content>)?.Content.Role is "user" or "function";

Try / catch

try { await geminiAgent.GenerateReplyAsync(messages, options, ct); }
catch (ArgumentException e) when (e.Message.Contains("first message must be from the user"))
{ /* reorder history to put a user/function message first and retry */ }

Prevention

When it happens

Trigger: Passing a chat history whose first message is from the assistant (e.g. you saved a prior Gemini reply first), a system-role Content, or a function-result-after-model ordering that leaves a model message at index 0.

Common situations: Replaying persisted conversations starting with the assistant, group-chat forwarding where another agent spoke first, or seed messages inserted in the wrong order.

Related errors


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