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
- Remap the message to one of System, User, Assistant, or Tool before sending.
- If you need a 'developer' role, upgrade the connector to a version that maps it.
- 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
- Do not construct AuthorRole from arbitrary strings.
- Map experimental roles (developer) to System on older builds.
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
- Failed to get a response from the chat completion service.
- The provided reasoning effort '{textEffortLevel}' is not sup
- The provided reasoning effort '{effortLevelObject.GetType()}
- The provided web search options '{executionSettings.WebSearc
- Unsupported chat message content type '{item.GetType()}'.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/b2d1111649d7028e.
Report an issue: GitHub.