{"record":{"id":"f9d5cc94ac0388ed","repo":"microsoft/semantic-kernel","slug":"last-message-in-chat-history-was-null-or-whitespac","errorCode":null,"errorMessage":"Last message in chat history was null or whitespace.","messagePattern":"Last message in chat history was null or whitespace\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Connectors/Connectors.Amazon/Bedrock/Core/BedrockModelUtilities.cs","lineNumber":64,"sourceCode":"            .Where(m => m.Role == AuthorRole.System)\n            .Select(m => new SystemContentBlock { Text = m.Content })\n            .ToList();\n    }\n\n    /// <summary>\n    /// Creates the list of user and assistant messages for the Converse Request from the Chat History.\n    /// </summary>\n    /// <param name=\"chatHistory\">The ChatHistory object to be building the message list from.</param>\n    /// <returns>The list of messages for the converse request.</returns>\n    /// <exception cref=\"ArgumentException\">Thrown if invalid last message in chat history.</exception>\n    internal static List<Message> BuildMessageList(ChatHistory chatHistory)\n    {\n        // Check that the text from the latest message in the chat history  is not empty.\n        Verify.NotNullOrEmpty(chatHistory);\n        string? text = chatHistory[chatHistory.Count - 1].Content;\n        if (string.IsNullOrWhiteSpace(text))\n        {\n            throw new ArgumentException(\"Last message in chat history was null or whitespace.\");\n        }\n        return chatHistory\n            .Where(m => m.Role != AuthorRole.System)\n            .Select(m => new Message\n            {\n                Role = MapAuthorRoleToConversationRole(m.Role),\n                Content = [new() { Text = m.Content }]\n            })\n            .ToList();\n    }\n\n    /// <summary>\n    /// Gets the prompt execution settings extension data for the model request body build.\n    /// Returns null if the extension data value is not set (default is null if TValue is a nullable type).\n    /// </summary>\n    /// <param name=\"extensionData\">The execution settings extension data.</param>\n    /// <param name=\"key\">The key name of the settings parameter</param>\n    /// <typeparam name=\"TValue\">The value of the settings parameter</typeparam>","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Connectors/Connectors.Amazon/Bedrock/Core/BedrockModelUtilities.cs#L46-L82","documentation":"BedrockModelUtilities.BuildMessageList constructs Bedrock Messages from ChatHistory. It asserts that the LAST message's Content is not null, empty, or whitespace, throwing ArgumentException otherwise. Bedrock's Converse API requires the trailing message to carry actual text, so the connector refuses to build an empty final turn.","triggerScenarios":"Calling Bedrock chat completion with a ChatHistory whose final entry has null/empty/whitespace Content. Commonly: an empty assistant placeholder, a function-result message with no text, or a trailing message whose Content was cleared.","commonSituations":"Streaming/placeholder patterns that append an empty assistant message and forget to fill it. Function/tool result messages that store structured data but leave Content empty. UI drafts that submit before the user types anything. Reusing a ChatHistory object across calls after trimming content.","solutions":["Before invoking, ensure the last ChatHistory message has non-whitespace Content: append a real user prompt if the last entry is empty.","Remove trailing empty messages from ChatHistory before the call.","If the last message is a function/tool result, set its Content to a textual summary rather than leaving it empty."],"exampleFix":"// before - last message is empty\nchatHistory.AddMessage(AuthorRole.Assistant, \"\");\nawait chatCompletion.GetChatMessageContentAsync(chatHistory);\n// -> ArgumentException: Last message in chat history was null or whitespace.\n\n// after - guarantee the final message has content\nwhile (chatHistory.Count > 0\n       && string.IsNullOrWhiteSpace(chatHistory[^1].Content))\n{\n    chatHistory.RemoveAt(chatHistory.Count - 1);\n}\nchatHistory.AddUserMessage(\"Please continue.\");","handlingStrategy":"validation","validationCode":"// Ensure the last ChatHistory message has non-whitespace content before invoking.\nstatic void EnsureTrailingContent(ChatHistory chatHistory)\n{\n    if (chatHistory.Count == 0)\n        throw new ArgumentException(\"ChatHistory is empty.\");\n    while (chatHistory.Count > 0 && string.IsNullOrWhiteSpace(chatHistory[^1].Content))\n        chatHistory.RemoveAt(chatHistory.Count - 1);\n    if (chatHistory.Count == 0 || string.IsNullOrWhiteSpace(chatHistory[^1].Content))\n        throw new ArgumentException(\"ChatHistory must end with a non-empty message.\");\n}","typeGuard":"static bool HasValidTrailingMessage(ChatHistory chatHistory)\n    => chatHistory.Count > 0 && !string.IsNullOrWhiteSpace(chatHistory[^1].Content);","tryCatchPattern":"try\n{\n    var result = await bedrockChatCompletion.GetChatMessageContentAsync(chatHistory, settings, ct);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"null or whitespace\"))\n{\n    // Trim trailing empty messages and append a real prompt, then retry.\n    logger.LogWarning(ex, \"Last ChatHistory message was empty; sanitizing.\");\n}","preventionTips":["Never append empty/placeholder assistant messages without later setting their Content.","Add a pre-flight check that the final message has non-whitespace text.","When storing tool/function results, set Content to a textual summary."],"tags":["csharp","dotnet","semantic-kernel","bedrock","aws","chathistory","validation"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}