microsoft/autogen · error · ArgumentNullException
choice.Message.ToolCalls
Error message
choice.Message.ToolCalls
What it means
Thrown when a Mistral completion has finish_reason == 'tool_calls' but choice.Message.ToolCalls is null. The connector requires at least the ToolCalls collection to exist before mapping to ToolCallMessage; a null list means the response contract was violated. Thrown via the null-coalescing throw expression at MistralChatMessageConnector.cs:160.
Source
Thrown at dotnet/src/AutoGen.Mistral/Middleware/MistralChatMessageConnector.cs:160
{
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")
{
throw new NotSupportedException($"VarObject {response.VarObject} is not supported");
}
if (response.Choices is null)
{View on GitHub (pinned to 027ecf0a37)
Solutions
- Log the raw response JSON and verify the tool_calls field name and shape match the SDK's FunctionContent model.
- If writing tests/mocks, always populate ToolCalls (even an empty list) whenever FinishReason is ToolCalls.
- If the live API shape changed, update the response model classes in AutoGen.Mistral accordingly.
- Upgrade to the latest AutoGen.Mistral package.
Example fix
// before
var functionContents = choice.Message?.ToolCalls ?? throw new ArgumentNullException("choice.Message.ToolCalls");
// after
var functionContents = choice.Message?.ToolCalls ?? new List<ToolCallContent>(); // then handle empty below
if (functionContents.Count == 0) throw new InvalidOperationException("finish_reason=tool_calls but tool_calls list is empty"); Defensive patterns
Strategy: validation
Validate before calling
if (choice.FinishReason == Choice.FinishReasonEnum.ToolCalls
&& (choice.Message?.ToolCalls is null || choice.Message.ToolCalls.Count == 0))
{
throw new InvalidOperationException("finish_reason=tool_calls but no tool calls present; check API/model version");
} Type guard
static bool HasToolCalls(Choice choice) =>
choice?.Message?.ToolCalls is { Count: > 0 }; Try / catch
catch (ArgumentNullException ex) when (ex.Message.Contains("choice.Message.ToolCalls"))
{
logger.LogError(ex, "Malformed tool-call completion; inspect raw response");
throw; // data integrity issue: do not silently continue
} Prevention
- When mocking ChatCompletionResponse, always populate ToolCalls when FinishReason is ToolCalls
- Verify tool schemas are correctly registered so the model can actually emit calls
When it happens
Trigger: Non-streaming Mistral call where finish_reason is 'tool_calls' yet the message payload contains no tool_calls array (or it deserializes to null because of a renamed field). Also occurs with hand-crafted/mocked ChatCompletionResponse objects that set FinishReason but forget ToolCalls.
Common situations: Unit tests with hand-built response fixtures missing ToolCalls; Mistral API schema drift (field renamed or restructured); a truncated response from a proxy or gateway that strips tool_calls.
Related errors
- choice.Message.Content
- Value was null.
- Tool call message from another agent is not supported
- Failed to deserialize response
- Missing MISTRAL_API_KEY environment variable
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/6380422b17058df8.
Report an issue: GitHub.