{"record":{"id":"ac2bd0807a0ea3ce","repo":"dotnet/machinelearning","slug":"please-provide-a-message-with-content","errorCode":null,"errorMessage":"Please provide a message with content.","messagePattern":"Please provide a message with content\\.","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.GenAI.LLaMA/Llama3_1ChatTemplateBuilder.cs","lineNumber":25,"sourceCode":"using Microsoft.Extensions.AI;\nusing Microsoft.ML.GenAI.Core;\nusing Microsoft.SemanticKernel;\nusing Microsoft.SemanticKernel.ChatCompletion;\nusing TextContent = Microsoft.SemanticKernel.TextContent;\n\nnamespace Microsoft.ML.GenAI.LLaMA;\n#pragma warning disable MSML_GeneralName // This name should be PascalCased\npublic class Llama3_1ChatTemplateBuilder : IChatTemplateBuilder, IMEAIChatTemplateBuilder\n#pragma warning restore MSML_GeneralName // This name should be PascalCased\n{\n    private const char Newline = '\\n';\n\n    public string BuildPrompt(IEnumerable<IMessage> messages, IEnumerable<FunctionContract>? tools = null)\n    {\n        var availableRoles = new[] { Role.System, Role.User, Role.Assistant };\n        if (messages.Any(m => m.GetContent() is null))\n        {\n            throw new InvalidOperationException(\"Please provide a message with content.\");\n        }\n\n        if (messages.Any(m => m.GetRole() is null || availableRoles.Contains(m.GetRole()!.Value) == false))\n        {\n            throw new InvalidOperationException(\"Please provide a message with a valid role. The valid roles are System, User, and Assistant.\");\n        }\n\n        // construct template based on instruction from\n        // https://github.com/meta-llama/llama3/blob/11817d47e1ba7a4959b025eb1ca308572e0e3963/llama/generation.py#L280\n\n        var sb = new StringBuilder();\n        sb.Append(\"<|begin_of_text|>\");\n        foreach (var message in messages)\n        {\n            var role = message.GetRole()!.Value;\n            var content = message.GetContent()!;\n            sb.Append(message switch\n            {","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.GenAI.LLaMA/Llama3_1ChatTemplateBuilder.cs#L7-L43","documentation":"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().","triggerScenarios":"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.","commonSituations":"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.","solutions":["Filter or skip messages with null content before calling BuildPrompt.","Replace null content with an empty string or a descriptive placeholder if the message must be kept.","Ensure upstream message-construction code always sets non-null content.","Convert non-text messages (tool calls, images) to their text representation before building the prompt."],"exampleFix":"// before\nvar prompt = builder.BuildPrompt(messages);\n// after\nvar prompt = builder.BuildPrompt(messages.Where(m => m.GetContent() is not null));","handlingStrategy":"validation","validationCode":"if (messages.Any(m => m.GetContent() is null))\n    throw new InvalidOperationException(\"All messages must have non-null content before BuildPrompt.\");","typeGuard":"static bool HasContent(IMessage m) => m.GetContent() is not null;\nvar safe = messages.Where(HasContent);","tryCatchPattern":"try { prompt = builder.BuildPrompt(messages); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"content\"))\n{ prompt = builder.BuildPrompt(messages.Where(m => m.GetContent() is not null)); }","preventionTips":["Sanitize chat history (drop or fill null-content messages) at pipeline entry.","Convert tool-call/image messages to text before LLaMA prompt building.","Unit-test the template builder with realistic histories including tool messages."],"tags":["llama","prompt-template","null-content","validation"],"backgroundTag":"null-argument","analyzedSha":"7b76e69cf964daeca3f1377af6bc5543284d56c6","analyzedAt":"2026-09-11T12:35:38.930Z","contentChangedAt":"2026-09-11T12:35:38.930Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}