{"record":{"id":"5ca1ec248d0e8e74","repo":"dotnet/machinelearning","slug":"please-provide-a-message-with-content-5ca1ec","errorCode":null,"errorMessage":"Please provide a message with content.","messagePattern":"Please provide a message with content\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.GenAI.Phi/Phi3/Phi3ChatTemplateBuilder.cs","lineNumber":30,"sourceCode":"using Microsoft.ML.GenAI.Core;\nusing Microsoft.SemanticKernel;\nusing Microsoft.SemanticKernel.ChatCompletion;\nusing TextContent = Microsoft.SemanticKernel.TextContent;\n\nnamespace Microsoft.ML.GenAI.Phi;\n\npublic class Phi3ChatTemplateBuilder : IChatTemplateBuilder, IMEAIChatTemplateBuilder\n{\n    private const char Newline = '\\n';\n\n    public static Phi3ChatTemplateBuilder Instance { get; } = new Phi3ChatTemplateBuilder();\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://huggingface.co/microsoft/Phi-3-mini-128k-instruct#chat-format\n\n        var sb = new StringBuilder();\n        foreach (var message in messages)\n        {\n            var role = message.GetRole()!.Value;\n            var content = message.GetContent()!;\n            sb.Append(message switch\n            {\n                _ when message.GetRole() == Role.System => $\"<|system|>{Newline}{content}<|end|>{Newline}\",","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.GenAI.Phi/Phi3/Phi3ChatTemplateBuilder.cs#L12-L48","documentation":"Phi3ChatTemplateBuilder.BuildPrompt(IEnumerable<IMessage>) validates that every message has non-null content before rendering the Phi-3 chat template. Any message whose GetContent() is null makes the prompt impossible to render, so it throws InvalidOperationException.","triggerScenarios":"Passing a message collection to BuildPrompt where at least one IMessage has null content — e.g. a message constructed from a null string, a tool-call-only message, or deserialization that left Content unset.","commonSituations":"Binding chat history from external JSON where 'content' was absent; creating TextMessage with a null body programmatically; including function-call result messages that carry no textual content.","solutions":["Filter out messages with null content before calling BuildPrompt.","Replace null-content messages with a placeholder string such as string.Empty or '[no content]'.","Fix upstream message construction/deserialization so Content is always populated."],"exampleFix":"// before\nvar prompt = builder.BuildPrompt(messages);\n// after\nvar prompt = builder.BuildPrompt(messages.Where(m => m.GetContent() is not null));","handlingStrategy":"validation","validationCode":"bool allHaveContent = messages.All(m => m.GetContent() is not null);\nif (!allHaveContent) throw new InvalidOperationException(\"All messages must have content before building the Phi-3 prompt.\");","typeGuard":"bool HasContent(IMessage m) => m.GetContent() is not null;","tryCatchPattern":"try { var prompt = builder.BuildPrompt(messages); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"message with content\")) { messages = messages.Where(m => m.GetContent() is not null); prompt = builder.BuildPrompt(messages); }","preventionTips":["Validate chat history at ingestion time, not at template-build time.","Never construct TextMessage with a null body — use string.Empty if needed.","Sanitize deserialized messages before adding them to history."],"tags":["csharp","llm","chat-template","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"}