{"record":{"id":"7a68c13003620adc","repo":"dotnet/machinelearning","slug":"invalid-role","errorCode":null,"errorMessage":"Invalid role.","messagePattern":"Invalid role\\.","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.ML.GenAI.LLaMA/Llama3_1ChatTemplateBuilder.cs","lineNumber":47,"sourceCode":"        {\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            });\n        }\n\n        sb.Append($\"<|start_header_id|>assistant<|end_header_id|>{Newline}\");\n        var input = sb.ToString();\n\n        return input;\n    }\n\n    public string BuildPrompt(ChatHistory chatHistory)\n    {\n        // build prompt from chat history\n        var sb = new StringBuilder();\n\n        sb.Append(\"<|begin_of_text|>\");\n        foreach (var message in chatHistory)\n        {\n            foreach (var item in message.Items)","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/dotnet/machinelearning/blob/7b76e69cf964daeca3f1377af6bc5543284d56c6/src/Microsoft.ML.GenAI.LLaMA/Llama3_1ChatTemplateBuilder.cs#L29-L65","documentation":"Exhaustive switch fallback inside BuildPrompt's prompt-assembly loop. Given the preceding validation, this is an internal-invariant guard: if execution reaches it, a message role passed all earlier checks but matched none of the System/User/Assistant branches.","triggerScenarios":"A message whose GetRole() returned a value that slipped past the earlier role validation (e.g. a custom Role value that compares unequal in the switch but was accepted earlier, or validation executed over a different message collection than the one rendered).","commonSituations":"Custom Role static members added by consumers that don't equal the canonical three; collections mutated between validation and rendering; role comparisons relying on reference equality with differing Role instances.","solutions":["Use only the canonical Role.System, Role.User, Role.Assistant values (don't define look-alike roles).","Verify the same messages collection is validated and rendered.","Normalize roles to the canonical three before calling BuildPrompt.","If you believe roles are valid, inspect message.GetRole() values to find the unexpected one."],"exampleFix":"// before\nvar role = new Role(\"assistant\"); // look-alike, not the canonical member\n// after\nvar role = Role.Assistant; // canonical value","handlingStrategy":"validation","validationCode":"var canonical = new HashSet<Role> { Role.System, Role.User, Role.Assistant };\nif (messages.Any(m => !canonical.Contains(m.GetRole()!.Value)))\n    throw new InvalidOperationException(\"Non-canonical role detected before BuildPrompt.\");","typeGuard":"static bool IsCanonicalRole(IMessage m) =>\n    ReferenceEquals(m.GetRole(), Role.System) ||\n    ReferenceEquals(m.GetRole(), Role.User) ||\n    ReferenceEquals(m.GetRole(), Role.Assistant);","tryCatchPattern":"try { prompt = builder.BuildPrompt(messages); }\ncatch (InvalidOperationException ex) when (ex.Message == \"Invalid role.\")\n{ log.Error(\"Role slipped past validation; check for custom Role instances\"); throw; }","preventionTips":["Use only the canonical Role static members; avoid look-alike instances.","Freeze the message list (ToList) before validation and rendering.","Treat this throw as a bug signal and log the offending role value."],"tags":["llama","prompt-template","invariant","invalid-role"],"backgroundTag":"internal-invariant-violation","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"}