dotnet/machinelearning · error · InvalidOperationException

Invalid role.

Error message

Invalid role.

What it means

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.

Source

Thrown at src/Microsoft.ML.GenAI.LLaMA/Llama3_1ChatTemplateBuilder.cs:47

        {
            throw new InvalidOperationException("Please provide a message with a valid role. The valid roles are System, User, and Assistant.");
        }

        // construct template based on instruction from
        // https://github.com/meta-llama/llama3/blob/11817d47e1ba7a4959b025eb1ca308572e0e3963/llama/generation.py#L280

        var sb = new StringBuilder();
        sb.Append("<|begin_of_text|>");
        foreach (var message in messages)
        {
            var role = message.GetRole()!.Value;
            var content = message.GetContent()!;
            sb.Append(message switch
            {
                _ when message.GetRole() == Role.System => $"<|start_header_id|>system<|end_header_id|>{Newline}{content.Trim()}<|eot_id|>{Newline}",
                _ when message.GetRole() == Role.User => $"<|start_header_id|>user<|end_header_id|>{Newline}{content.Trim()}<|eot_id|>{Newline}",
                _ when message.GetRole() == Role.Assistant => $"<|start_header_id|>assistant<|end_header_id|>{Newline}{content.Trim()}<|eot_id|>{Newline}",
                _ => throw new InvalidOperationException("Invalid role.")
            });
        }

        sb.Append($"<|start_header_id|>assistant<|end_header_id|>{Newline}");
        var input = sb.ToString();

        return input;
    }

    public string BuildPrompt(ChatHistory chatHistory)
    {
        // build prompt from chat history
        var sb = new StringBuilder();

        sb.Append("<|begin_of_text|>");
        foreach (var message in chatHistory)
        {
            foreach (var item in message.Items)

View on GitHub (pinned to 7b76e69cf9)

Solutions

  1. Use only the canonical Role.System, Role.User, Role.Assistant values (don't define look-alike roles).
  2. Verify the same messages collection is validated and rendered.
  3. Normalize roles to the canonical three before calling BuildPrompt.
  4. If you believe roles are valid, inspect message.GetRole() values to find the unexpected one.

Example fix

// before
var role = new Role("assistant"); // look-alike, not the canonical member
// after
var role = Role.Assistant; // canonical value
Defensive patterns

Strategy: validation

Validate before calling

var canonical = new HashSet<Role> { Role.System, Role.User, Role.Assistant };
if (messages.Any(m => !canonical.Contains(m.GetRole()!.Value)))
    throw new InvalidOperationException("Non-canonical role detected before BuildPrompt.");

Type guard

static bool IsCanonicalRole(IMessage m) =>
    ReferenceEquals(m.GetRole(), Role.System) ||
    ReferenceEquals(m.GetRole(), Role.User) ||
    ReferenceEquals(m.GetRole(), Role.Assistant);

Try / catch

try { prompt = builder.BuildPrompt(messages); }
catch (InvalidOperationException ex) when (ex.Message == "Invalid role.")
{ log.Error("Role slipped past validation; check for custom Role instances"); throw; }

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11). Data as JSON: /api/errors/7a68c13003620adc. Report an issue: GitHub.