microsoft/semantic-kernel · error · ArgumentException

Last message in chat history was null or whitespace.

Error message

Last message in chat history was null or whitespace.

What it means

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.

Source

Thrown at dotnet/src/Connectors/Connectors.Amazon/Bedrock/Core/BedrockModelUtilities.cs:64

            .Where(m => m.Role == AuthorRole.System)
            .Select(m => new SystemContentBlock { Text = m.Content })
            .ToList();
    }

    /// <summary>
    /// Creates the list of user and assistant messages for the Converse Request from the Chat History.
    /// </summary>
    /// <param name="chatHistory">The ChatHistory object to be building the message list from.</param>
    /// <returns>The list of messages for the converse request.</returns>
    /// <exception cref="ArgumentException">Thrown if invalid last message in chat history.</exception>
    internal static List<Message> BuildMessageList(ChatHistory chatHistory)
    {
        // Check that the text from the latest message in the chat history  is not empty.
        Verify.NotNullOrEmpty(chatHistory);
        string? text = chatHistory[chatHistory.Count - 1].Content;
        if (string.IsNullOrWhiteSpace(text))
        {
            throw new ArgumentException("Last message in chat history was null or whitespace.");
        }
        return chatHistory
            .Where(m => m.Role != AuthorRole.System)
            .Select(m => new Message
            {
                Role = MapAuthorRoleToConversationRole(m.Role),
                Content = [new() { Text = m.Content }]
            })
            .ToList();
    }

    /// <summary>
    /// Gets the prompt execution settings extension data for the model request body build.
    /// Returns null if the extension data value is not set (default is null if TValue is a nullable type).
    /// </summary>
    /// <param name="extensionData">The execution settings extension data.</param>
    /// <param name="key">The key name of the settings parameter</param>
    /// <typeparam name="TValue">The value of the settings parameter</typeparam>

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Before invoking, ensure the last ChatHistory message has non-whitespace Content: append a real user prompt if the last entry is empty.
  2. Remove trailing empty messages from ChatHistory before the call.
  3. If the last message is a function/tool result, set its Content to a textual summary rather than leaving it empty.

Example fix

// before - last message is empty
chatHistory.AddMessage(AuthorRole.Assistant, "");
await chatCompletion.GetChatMessageContentAsync(chatHistory);
// -> ArgumentException: Last message in chat history was null or whitespace.

// after - guarantee the final message has content
while (chatHistory.Count > 0
       && string.IsNullOrWhiteSpace(chatHistory[^1].Content))
{
    chatHistory.RemoveAt(chatHistory.Count - 1);
}
chatHistory.AddUserMessage("Please continue.");
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the last ChatHistory message has non-whitespace content before invoking.
static void EnsureTrailingContent(ChatHistory chatHistory)
{
    if (chatHistory.Count == 0)
        throw new ArgumentException("ChatHistory is empty.");
    while (chatHistory.Count > 0 && string.IsNullOrWhiteSpace(chatHistory[^1].Content))
        chatHistory.RemoveAt(chatHistory.Count - 1);
    if (chatHistory.Count == 0 || string.IsNullOrWhiteSpace(chatHistory[^1].Content))
        throw new ArgumentException("ChatHistory must end with a non-empty message.");
}

Type guard

static bool HasValidTrailingMessage(ChatHistory chatHistory)
    => chatHistory.Count > 0 && !string.IsNullOrWhiteSpace(chatHistory[^1].Content);

Try / catch

try
{
    var result = await bedrockChatCompletion.GetChatMessageContentAsync(chatHistory, settings, ct);
}
catch (ArgumentException ex) when (ex.Message.Contains("null or whitespace"))
{
    // Trim trailing empty messages and append a real prompt, then retry.
    logger.LogWarning(ex, "Last ChatHistory message was empty; sanitizing.");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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