dotnet/machinelearning · error · InvalidOperationException

Please provide a message with content.

Error message

Please provide a message with content.

What it means

The Llama 3.1 chat template builder requires every message to carry non-null content, because the LLaMA prompt format embeds each message's text between header/eot tags. It throws InvalidOperationException when any IMessage in the sequence returns null from GetContent().

Source

Thrown at src/Microsoft.ML.GenAI.LLaMA/Llama3_1ChatTemplateBuilder.cs:25

using Microsoft.Extensions.AI;
using Microsoft.ML.GenAI.Core;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using TextContent = Microsoft.SemanticKernel.TextContent;

namespace Microsoft.ML.GenAI.LLaMA;
#pragma warning disable MSML_GeneralName // This name should be PascalCased
public class Llama3_1ChatTemplateBuilder : IChatTemplateBuilder, IMEAIChatTemplateBuilder
#pragma warning restore MSML_GeneralName // This name should be PascalCased
{
    private const char Newline = '\n';

    public string BuildPrompt(IEnumerable<IMessage> messages, IEnumerable<FunctionContract>? tools = null)
    {
        var availableRoles = new[] { Role.System, Role.User, Role.Assistant };
        if (messages.Any(m => m.GetContent() is null))
        {
            throw new InvalidOperationException("Please provide a message with content.");
        }

        if (messages.Any(m => m.GetRole() is null || availableRoles.Contains(m.GetRole()!.Value) == false))
        {
            throw new InvalidOperationException("Please provide a message with a valid role. The valid roles are System, User, and Assistant.");
        }

        // construct template based on instruction from
        // https://github.com/meta-llama/llama3/blob/11817d47e1ba7a4959b025eb1ca308572e0e3963/llama/generation.py#L280

        var sb = new StringBuilder();
        sb.Append("<|begin_of_text|>");
        foreach (var message in messages)
        {
            var role = message.GetRole()!.Value;
            var content = message.GetContent()!;
            sb.Append(message switch
            {

View on GitHub (pinned to 7b76e69cf9)

Solutions

  1. Filter or skip messages with null content before calling BuildPrompt.
  2. Replace null content with an empty string or a descriptive placeholder if the message must be kept.
  3. Ensure upstream message-construction code always sets non-null content.
  4. Convert non-text messages (tool calls, images) to their text representation before building the prompt.

Example fix

// before
var prompt = builder.BuildPrompt(messages);
// after
var prompt = builder.BuildPrompt(messages.Where(m => m.GetContent() is not null));
Defensive patterns

Strategy: validation

Validate before calling

if (messages.Any(m => m.GetContent() is null))
    throw new InvalidOperationException("All messages must have non-null content before BuildPrompt.");

Type guard

static bool HasContent(IMessage m) => m.GetContent() is not null;
var safe = messages.Where(HasContent);

Try / catch

try { prompt = builder.BuildPrompt(messages); }
catch (InvalidOperationException ex) when (ex.Message.Contains("content"))
{ prompt = builder.BuildPrompt(messages.Where(m => m.GetContent() is not null)); }

Prevention

When it happens

Trigger: Calling BuildPrompt(IEnumerable<IMessage>, ...) with a message whose GetContent() is null — e.g. a message constructed without content, a tool/function-call message whose payload is not text, or a message deserialized with a missing content field.

Common situations: Feeding tool-call or image messages into the text-only LLaMA template; constructing TextMessage with a null body from an upstream model response; pipeline stages that emit role-only placeholder messages.

Related errors


AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11). Data as JSON: /api/errors/ac2bd0807a0ea3ce. Report an issue: GitHub.