microsoft/autogen · error · ArgumentNullException

choice.Message.Content

Error message

choice.Message.Content

What it means

Thrown by MistralChatMessageConnector when a Mistral chat completion finishes with reason 'stop' or 'length' but the returned choice.Message.Content is null. The connector assumes a text finish always carries content, so a null Content is treated as a programming/contract violation rather than a normal result. It is an ArgumentNullException thrown via the null-coalescing throw expression at MistralChatMessageConnector.cs:156.

Source

Thrown at dotnet/src/AutoGen.Mistral/Middleware/MistralChatMessageConnector.cs:156

    private IMessage PostProcessMessage(ChatCompletionResponse response, IAgent from)
    {
        if (response.Choices is null)
        {
            throw new ArgumentNullException("response.Choices");
        }

        if (response.Choices?.Count != 1)
        {
            throw new NotSupportedException("response.Choices.Count != 1");
        }

        var choice = response.Choices[0];
        var finishReason = choice.FinishReason ?? throw new ArgumentNullException("choice.FinishReason");

        if (finishReason == Choice.FinishReasonEnum.Stop || finishReason == Choice.FinishReasonEnum.Length)
        {
            return new TextMessage(Role.Assistant, choice.Message?.Content ?? throw new ArgumentNullException("choice.Message.Content"), from: from.Name);
        }
        else if (finishReason == Choice.FinishReasonEnum.ToolCalls)
        {
            var functionContents = choice.Message?.ToolCalls ?? throw new ArgumentNullException("choice.Message.ToolCalls");
            var toolCalls = functionContents.Select(f => new ToolCall(f.Function.Name, f.Function.Arguments) { ToolCallId = f.Id }).ToList();
            return new ToolCallMessage(toolCalls, from: from.Name);
        }
        else
        {
            throw new NotSupportedException($"FinishReason {finishReason} is not supported");
        }
    }

    private IMessage? ProcessChatCompletionResponse(IMessage<ChatCompletionResponse> message, IAgent agent)
    {
        var response = message.Content;
        if (response.VarObject != "chat.completion.chunk")
        {

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Inspect the raw HTTP response body for the failing request to see the actual Content JSON shape (log it before deserialization).
  2. If Content can legitimately be empty, map null to string.Empty instead of throwing: choice.Message?.Content ?? string.Empty.
  3. If the API payload changed, update the ChatCompletionResponse model (e.g. change Content from string to a nullable/JsonElement property) to match the current Mistral API.
  4. Upgrade AutoGen.Mistral to the latest version in case the connector was already patched for this shape.

Example fix

// before
return new TextMessage(Role.Assistant, choice.Message?.Content ?? throw new ArgumentNullException("choice.Message.Content"), from: from.Name);

// after
return new TextMessage(Role.Assistant, choice.Message?.Content ?? string.Empty, from: from.Name);
Defensive patterns

Strategy: validation

Validate before calling

var choice = response.Choices[0];
if (choice.FinishReason is Choice.FinishReasonEnum.Stop or Choice.FinishReasonEnum.Length
    && string.IsNullOrEmpty(choice.Message?.Content))
{
    // model finished with no text; decide policy before the connector throws
    choice.Message.Content = string.Empty;
}

Type guard

static bool HasTextContent(Choice choice) =>
    choice?.Message?.Content is string s && s.Length > 0;

Try / catch

catch (ArgumentNullException ex) when (ex.Message.Contains("choice.Message.Content"))
{
    // treat as empty completion and retry or continue conversation
    logger.LogWarning("Mistral returned empty content for stop/length finish");
}

Prevention

When it happens

Trigger: Calling a Mistral agent (non-streaming path) where the model's finish_reason is 'stop' or 'length' while choice.Message.Content deserializes to null. This happens when the model returns only tool_calls with empty content, when the JSON payload shape changes (new Mistral API version), or when Content is an unexpected JSON type (e.g. an array payload) that System.Text.Json maps to null.

Common situations: Mistral API returning content as a structured payload instead of a plain string; a model finishing with 'length' after emitting no text; version drift between the vendored Mistral SDK models and the live Mistral API; a response produced entirely of tool calls but mislabeled finish_reason.

Related errors


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