microsoft/semantic-kernel · error · NotSupportedException

Role {message.Role} is not supported.

Error message

Role {message.Role} is not supported.

What it means

Terminal throw at the end of the per-role message builder. The method handles System, User, Assistant, and Tool roles explicitly; reaching this line means message.Role is none of those (e.g. an unknown/custom AuthorRole label). OpenAI's chat protocol has no slot for such a role, so the request cannot be serialized.

Source

Thrown at dotnet/src/Connectors/Connectors.OpenAI/Core/ClientCore.ChatCompletion.cs:885

            }

            // This check is necessary to prevent an exception that will be thrown if the toolCalls collection is empty.
            // HTTP 400 (invalid_request_error:) [] should be non-empty - 'messages.3.tool_calls'
            if (toolCalls.Count == 0)
            {
                return [new AssistantChatMessage(message.Content ?? string.Empty) { ParticipantName = message.AuthorName }];
            }

            var assistantMessage = new AssistantChatMessage(SanitizeFunctionNames(toolCalls)) { ParticipantName = message.AuthorName };

            // If message content is null, adding it as empty string,
            // because chat message content must be string.
            assistantMessage.Content.Add(message.Content ?? string.Empty);

            return [assistantMessage];
        }

        throw new NotSupportedException($"Role {message.Role} is not supported.");
    }

    private static ChatMessageContentPart GetImageContentItem(ImageContent imageContent)
    {
        ChatImageDetailLevel? detailLevel = GetChatImageDetailLevel(imageContent);

        if (imageContent.Data is { IsEmpty: false } data)
        {
            return ChatMessageContentPart.CreateImagePart(BinaryData.FromBytes(data), imageContent.MimeType, detailLevel);
        }

        if (imageContent.Uri is not null)
        {
            return ChatMessageContentPart.CreateImagePart(imageContent.Uri, detailLevel);
        }

        throw new ArgumentException($"{nameof(ImageContent)} must have either Data or a Uri.");
    }

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Remap the message to one of System, User, Assistant, or Tool before sending.
  2. If you need a 'developer' role, upgrade the connector to a version that maps it.
  3. Avoid creating AuthorRole instances from arbitrary strings.

Example fix

// before
history.Add(new ChatMessageContent(new AuthorRole("developer"), "act as X"));
// after
history.Add(new ChatMessageContent(AuthorRole.System, "act as X"));
Defensive patterns

Strategy: validation

Validate before calling

static readonly HashSet<AuthorRole> SupportedRoles = new() { AuthorRole.System, AuthorRole.User, AuthorRole.Assistant, AuthorRole.Tool };
static void EnsureSupportedRole(ChatMessageContent m) { if (!SupportedRoles.Contains(m.Role)) throw new ArgumentException($"Remap role {m.Role} to System/User/Assistant/Tool"); }

Type guard

static bool IsSupportedRole(AuthorRole? r) => r is not null && SupportedRoles.Contains(r);

Try / catch

try { await client.GetChatCompletionAsync(history); }
catch (NotSupportedException ex) when (ex.Message.Contains("is not supported")) { /* remap role and retry */ }

Prevention

When it happens

Trigger: Passing a ChatMessageContent whose AuthorRole is a custom label or a role outside System/User/Assistant/Tool (e.g. AuthorRole.System analog misspelled, or a generic 'developer' role not yet handled by this version).

Common situations: Using newer role vocabulary (developer) on an older connector build; constructing messages with string-based custom roles; deserializing history that used an experimental role.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/b2d1111649d7028e. Report an issue: GitHub.