microsoft/semantic-kernel · error · ArgumentException

The first message in chat history must have either the syste

Error message

The first message in chat history must have either the system or user role

What it means

Thrown by MistralClient.ValidateChatHistory when the first message in ChatHistory has a role other than 'system' or 'user'. The Mistral API expects conversations to begin with a user or system message; starting with an assistant or tool message is invalid. This is enforced client-side as an ArgumentException.

Source

Thrown at dotnet/src/Connectors/Connectors.MistralAI/Client/MistralClient.cs:675

        s_completionTokensCounter.Add(usage.CompletionTokens.Value);
        s_totalTokensCounter.Add(usage.TotalTokens.Value);
    }

    /// <summary>
    /// Messages are required and the first prompt role should be user or system.
    /// </summary>
    private void ValidateChatHistory(ChatHistory chatHistory)
    {
        Verify.NotNull(chatHistory);

        if (chatHistory.Count == 0)
        {
            throw new ArgumentException("Chat history must contain at least one message", nameof(chatHistory));
        }
        var firstRole = chatHistory[0].Role.ToString();
        if (firstRole is not "system" and not "user")
        {
            throw new ArgumentException("The first message in chat history must have either the system or user role", nameof(chatHistory));
        }
    }

    private ChatCompletionRequest CreateChatCompletionRequest(string modelId, bool stream, ChatHistory chatHistory, MistralAIPromptExecutionSettings executionSettings, Kernel? kernel = null)
    {
        if (this._logger.IsEnabled(LogLevel.Trace))
        {
            this._logger.LogTrace("ChatHistory: {ChatHistory}, Settings: {Settings}",
                JsonSerializer.Serialize(chatHistory, JsonOptionsCache.ChatHistory),
                JsonSerializer.Serialize(executionSettings));
        }

        var request = new ChatCompletionRequest(modelId)
        {
            Stream = stream,
            Messages = chatHistory.SelectMany(chatMessage => this.ToMistralChatMessages(chatMessage, executionSettings?.ToolCallBehavior)).ToList(),
            Temperature = executionSettings.Temperature,
            TopP = executionSettings.TopP,

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Insert a user or system message as the first element of ChatHistory.
  2. If seeding context, use history.AddSystemMessage(...) or history.AddUserMessage(...) before any assistant/tool messages.
  3. Validate and reorder loaded history: ensure messages[0].Role is user or system before calling the API.

Example fix

// before
var history = new ChatHistory();
history.AddAssistantMessage("Sure, I can help.");

// after
var history = new ChatHistory();
history.AddSystemMessage("You are a helpful assistant.");
history.AddAssistantMessage("Sure, I can help.");
Defensive patterns

Strategy: validation

Validate before calling

if (chatHistory.Count > 0)
{
    var firstRole = chatHistory[0].Role.ToString();
    if (firstRole is not "system" and not "user")
        throw new InvalidOperationException("First message must be system or user role.");
}

Type guard

static bool HasValidFirstRole(ChatHistory history) =>
    history.Count == 0 ||
    history[0].Role.ToString() is "system" or "user";

Prevention

When it happens

Trigger: Building a ChatHistory whose first Add* call is history.AddAssistantMessage(...) or history.AddMessage(AuthorRole.Tool, ...); restoring a persisted conversation and accidentally ordering an assistant message first.

Common situations: Loading chat history from a database where the ordering got corrupted; replaying a tool-call sequence without a preceding user turn; multi-turn apps that prepend a previous assistant reply as context.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/5d65ee16c20e1ad2. Report an issue: GitHub.