{"record":{"id":"6380422b17058df8","repo":"microsoft/autogen","slug":"choice-message-toolcalls","errorCode":null,"errorMessage":"choice.Message.ToolCalls","messagePattern":"choice\\.Message\\.ToolCalls","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"dotnet/src/AutoGen.Mistral/Middleware/MistralChatMessageConnector.cs","lineNumber":160,"sourceCode":"        {\n            throw new ArgumentNullException(\"response.Choices\");\n        }\n\n        if (response.Choices?.Count != 1)\n        {\n            throw new NotSupportedException(\"response.Choices.Count != 1\");\n        }\n\n        var choice = response.Choices[0];\n        var finishReason = choice.FinishReason ?? throw new ArgumentNullException(\"choice.FinishReason\");\n\n        if (finishReason == Choice.FinishReasonEnum.Stop || finishReason == Choice.FinishReasonEnum.Length)\n        {\n            return new TextMessage(Role.Assistant, choice.Message?.Content ?? throw new ArgumentNullException(\"choice.Message.Content\"), from: from.Name);\n        }\n        else if (finishReason == Choice.FinishReasonEnum.ToolCalls)\n        {\n            var functionContents = choice.Message?.ToolCalls ?? throw new ArgumentNullException(\"choice.Message.ToolCalls\");\n            var toolCalls = functionContents.Select(f => new ToolCall(f.Function.Name, f.Function.Arguments) { ToolCallId = f.Id }).ToList();\n            return new ToolCallMessage(toolCalls, from: from.Name);\n        }\n        else\n        {\n            throw new NotSupportedException($\"FinishReason {finishReason} is not supported\");\n        }\n    }\n\n    private IMessage? ProcessChatCompletionResponse(IMessage<ChatCompletionResponse> message, IAgent agent)\n    {\n        var response = message.Content;\n        if (response.VarObject != \"chat.completion.chunk\")\n        {\n            throw new NotSupportedException($\"VarObject {response.VarObject} is not supported\");\n        }\n        if (response.Choices is null)\n        {","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/dotnet/src/AutoGen.Mistral/Middleware/MistralChatMessageConnector.cs#L142-L178","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar functionContents = choice.Message?.ToolCalls ?? throw new ArgumentNullException(\"choice.Message.ToolCalls\");\n\n// after\nvar functionContents = choice.Message?.ToolCalls ?? new List<ToolCallContent>(); // then handle empty below\nif (functionContents.Count == 0) throw new InvalidOperationException(\"finish_reason=tool_calls but tool_calls list is empty\");","handlingStrategy":"validation","validationCode":"if (choice.FinishReason == Choice.FinishReasonEnum.ToolCalls\n    && (choice.Message?.ToolCalls is null || choice.Message.ToolCalls.Count == 0))\n{\n    throw new InvalidOperationException(\"finish_reason=tool_calls but no tool calls present; check API/model version\");\n}","typeGuard":"static bool HasToolCalls(Choice choice) =>\n    choice?.Message?.ToolCalls is { Count: > 0 };","tryCatchPattern":"catch (ArgumentNullException ex) when (ex.Message.Contains(\"choice.Message.ToolCalls\"))\n{\n    logger.LogError(ex, \"Malformed tool-call completion; inspect raw response\");\n    throw; // data integrity issue: do not silently continue\n}","preventionTips":["When mocking ChatCompletionResponse, always populate ToolCalls when FinishReason is ToolCalls","Verify tool schemas are correctly registered so the model can actually emit calls"],"tags":["mistral","tool-calls","null-reference","deserialization"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}