{"record":{"id":"45ce31f45d2b7960","repo":"dotnet/machinelearning","slug":"please-provide-a-message-with-a-valid-role-the-va","errorCode":null,"errorMessage":"Please provide a message with a valid role. The valid roles are System, User, and Assistant.","messagePattern":"Please provide a message with a valid role\\. The valid roles are System, User, and Assistant\\.","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.GenAI.LLaMA/Llama3_1ChatTemplateBuilder.cs","lineNumber":30,"sourceCode":"\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            {\n                _ when message.GetRole() == Role.System => $\"<|start_header_id|>system<|end_header_id|>{Newline}{content.Trim()}<|eot_id|>{Newline}\",\n                _ when message.GetRole() == Role.User => $\"<|start_header_id|>user<|end_header_id|>{Newline}{content.Trim()}<|eot_id|>{Newline}\",\n                _ when message.GetRole() == Role.Assistant => $\"<|start_header_id|>assistant<|end_header_id|>{Newline}{content.Trim()}<|eot_id|>{Newline}\",\n                _ => throw new InvalidOperationException(\"Invalid role.\")\n            });","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.GenAI.LLaMA/Llama3_1ChatTemplateBuilder.cs#L12-L48","documentation":"The LLaMA 3.1 template only supports the roles System, User, and Assistant. BuildPrompt throws InvalidOperationException when a message's role is null or any other role (e.g. Tool/Function) is passed, because the LLaMA header format has no tag for such roles.","triggerScenarios":"Calling BuildPrompt(IEnumerable<IMessage>, ...) with messages whose GetRole() returns null or a role outside {System, User, Assistant} — typically tool/function-result messages or a custom role value.","commonSituations":"Including tool-call results in chat history meant for LLaMA prompting; using Role values from another framework's enum; appending system-like messages with a nonstandard role name.","solutions":["Map tool/function messages to User or Assistant text messages before building the prompt.","Filter out messages with unsupported roles from the sequence.","Ensure each message's Role is explicitly set to Role.System, Role.User, or Role.Assistant.","Translate third-party role enums to the library's Role type instead of passing raw values."],"exampleFix":"// before\nvar prompt = builder.BuildPrompt(history); // history contains Role.Tool messages\n// after\nvar mapped = history.Select(m => m.GetRole() == Role.Tool\n    ? new TextMessage(Role.User, m.GetContent()!, from: \"tool\")\n    : m);\nvar prompt = builder.BuildPrompt(mapped);","handlingStrategy":"validation","validationCode":"var valid = new[] { Role.System, Role.User, Role.Assistant };\nif (messages.Any(m => m.GetRole() is null || !valid.Contains(m.GetRole()!.Value)))\n    throw new InvalidOperationException(\"Unsupported role in history for LLaMA template.\");","typeGuard":"static bool HasValidRole(IMessage m) =>\n    m.GetRole() is Role r && r is Role.System or Role.User or Role.Assistant;","tryCatchPattern":"try { prompt = builder.BuildPrompt(messages); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"valid role\"))\n{ prompt = builder.BuildPrompt(messages.Where(HasValidRole)); }","preventionTips":["Map Tool/Function roles to User or Assistant before prompt building.","Always set Role explicitly when constructing messages.","Never pass raw role strings from other frameworks; convert to the library's Role type."],"tags":["llama","prompt-template","invalid-role","validation"],"backgroundTag":"invalid-enum-value","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"}