{"record":{"id":"e4f5b831f75d2d9c","repo":"dotnet/machinelearning","slug":"unsupported-role-message-role","errorCode":null,"errorMessage":"Unsupported role {message.Role}","messagePattern":"Unsupported role (.+?)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.GenAI.LLaMA/Llama3_1ChatTemplateBuilder.cs","lineNumber":79,"sourceCode":"\n        sb.Append(\"<|begin_of_text|>\");\n        foreach (var message in chatHistory)\n        {\n            foreach (var item in message.Items)\n            {\n                if (item is not TextContent textContent)\n                {\n                    throw new NotSupportedException($\"Only text content is supported, but got {item.GetType().Name}\");\n                }\n\n                var text = textContent.Text?.Trim() ?? string.Empty;\n\n                var prompt = message.Role switch\n                {\n                    _ when message.Role == AuthorRole.System => $\"<|start_header_id|>system<|end_header_id|>{Newline}{text}<|eot_id|>{Newline}\",\n                    _ when message.Role == AuthorRole.User => $\"<|start_header_id|>user<|end_header_id|>{Newline}{text}<|eot_id|>{Newline}\",\n                    _ when message.Role == AuthorRole.Assistant => $\"<|start_header_id|>assistant<|end_header_id|>{Newline}{text}<|eot_id|>{Newline}\",\n                    _ => throw new NotSupportedException($\"Unsupported role {message.Role}\")\n                };\n\n                sb.Append(prompt);\n            }\n        }\n\n        sb.Append($\"<|start_header_id|>assistant<|end_header_id|>{Newline}\");\n\n        return sb.ToString();\n    }\n\n    public string BuildPrompt(IEnumerable<ChatMessage> messages, ChatOptions? options = null, bool appendAssistantTag = true)\n    {\n        var availableRoles = new[] { ChatRole.System, ChatRole.User, ChatRole.Assistant };\n        if (messages.Any(m => m.Text is null))\n        {\n            throw new InvalidOperationException(\"Please provide a message with content.\");\n        }","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.GenAI.LLaMA/Llama3_1ChatTemplateBuilder.cs#L61-L97","documentation":"The LLaMA 3.1 template only renders messages authored as System, User, or Assistant. BuildPrompt throws NotSupportedException when a ChatMessage's Role is anything else (e.g. Tool), because the header format has no corresponding tag.","triggerScenarios":"Calling BuildPrompt(IEnumerable<ChatMessage>, ...) with a ChatMessage whose AuthorRole is Tool/Function or any custom role — typical when function-calling results are kept verbatim in chat history.","commonSituations":"Semantic Kernel function-calling pipelines adding Tool-role messages; converting histories from other providers with extra roles; custom AuthorRole values.","solutions":["Convert Tool-role messages to User or Assistant text messages before prompt building.","Remove Tool-role messages from the history passed to BuildPrompt.","Explicitly set AuthorRole on every message to System, User, or Assistant.","Merge tool output into the preceding assistant or a new user message."],"exampleFix":"// before\nvar prompt = builder.BuildPrompt(history); // contains AuthorRole.Tool\n// after\nvar mapped = history.Select(m => m.Role == AuthorRole.Tool\n    ? new ChatMessage(AuthorRole.User, m.Content)\n    : m);\nvar prompt = builder.BuildPrompt(mapped);","handlingStrategy":"validation","validationCode":"var valid = new[] { AuthorRole.System, AuthorRole.User, AuthorRole.Assistant };\nif (chatHistory.Any(m => !valid.Contains(m.Role)))\n    throw new InvalidOperationException(\"Unsupported AuthorRole in history for LLaMA template.\");","typeGuard":"static bool HasSupportedRole(ChatMessage m) =>\n    m.Role == AuthorRole.System || m.Role == AuthorRole.User || m.Role == AuthorRole.Assistant;","tryCatchPattern":"try { prompt = builder.BuildPrompt(chatHistory); }\ncatch (NotSupportedException ex) when (ex.Message.StartsWith(\"Unsupported role\"))\n{ prompt = builder.BuildPrompt(chatHistory.Where(HasSupportedRole)); }","preventionTips":["Convert Tool-role messages to User/Assistant text messages before prompt building.","Filter unsupported roles at the chat-history boundary.","Test with histories produced by function-calling pipelines, not just handcrafted ones."],"tags":["llama","semantic-kernel","invalid-role","function-calling"],"backgroundTag":"unsupported-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"}