microsoft/semantic-kernel · error · NotSupportedException
Unsupported role {message.Role.Label}. Only system, user, de
Error message
Unsupported role {message.Role.Label}. Only system, user, developer or assistant roles are allowed. What it means
ChatContentMessageExtensions.ToResponseItem converts a ChatMessageContent into an OpenAI Responses-API ResponseItem. It only recognizes the SYSTEM, USER, DEVELOPER, and ASSISTANT role labels; any other role throws NotSupportedException.
Source
Thrown at dotnet/src/Agents/OpenAI/Extensions/ChatContentMessageExtensions.cs:54
return messages.Select(message => message.ToThreadInitializationMessage());
}
/// <summary>
/// Converts a <see cref="ChatMessageContent"/> instance to a <see cref="ResponseItem"/>.
/// </summary>
/// <param name="message">The chat message content to convert.</param>
/// <returns>A <see cref="ResponseItem"/> instance.</returns>
public static ResponseItem ToResponseItem(this ChatMessageContent message)
{
var items = message.Items;
IEnumerable<ResponseContentPart> contentParts = items.Select(item => item.ToResponseContentPart());
return message.Role.Label.ToUpperInvariant() switch
{
"SYSTEM" => ResponseItem.CreateSystemMessageItem(contentParts),
"USER" => ResponseItem.CreateUserMessageItem(contentParts),
"DEVELOPER" => ResponseItem.CreateDeveloperMessageItem(contentParts),
"ASSISTANT" => ResponseItem.CreateAssistantMessageItem(contentParts),
_ => throw new NotSupportedException($"Unsupported role {message.Role.Label}. Only system, user, developer or assistant roles are allowed."),
};
}
}
View on GitHub (pinned to c028a0c7dc)
Solutions
- Filter the chat history to only system/user/developer/assistant messages before sending to a Responses-API agent.
- Convert tool-result messages into a user-role message (text) when the Responses API requires it.
- Use the correct agent type (OpenAIAssistantAgent vs OpenAIResponseAgent) for your message stream.
- Log message.Role.Label before conversion to detect unsupported roles.
Example fix
// before
var items = history.Select(m => m.ToResponseItem());
// after
var allowed = new[] { "SYSTEM", "USER", "DEVELOPER", "ASSISTANT" };
var items = history
.Where(m => allowed.Contains(m.Role.Label.ToUpperInvariant()))
.Select(m => m.ToResponseItem()); Defensive patterns
Strategy: type-guard
Validate before calling
var allowed = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "system", "user", "developer", "assistant" };
if (!allowed.Contains(message.Role.Label))
throw new ArgumentException($"Role '{message.Role.Label}' cannot be converted to a ResponseItem."); Type guard
static bool IsSupportedResponseRole(ChatMessageContent m) =>
m.Role.Label.ToUpperInvariant() is "SYSTEM" or "USER" or "DEVELOPER" or "ASSISTANT"; Try / catch
try { var item = message.ToResponseItem(); }
catch (NotSupportedException ex) when (ex.Message.Contains("Unsupported role")) {
// map tool/other messages to a user message, or drop them
} Prevention
- Filter history to supported roles before sending to a Responses-API agent.
- Keep a shared allow-list of roles for the converter.
- Avoid passing tool messages into Responses-API paths.
When it happens
Trigger: Passing a ChatMessageContent whose Role is Tool (or a custom AuthorRole) into the Responses-API conversion path used by OpenAIResponseAgent.
Common situations: Feeding a tool-result message or function-call content into a Responses-API agent that only accepts the four conversational roles; mixing Assistant-API message shapes with the Responses converter.
Related errors
- The agent thread is not a ChatHistoryAgentThread.
- OPENAI_API_KEY is not set.
- Invalid OpenAI client type '{connection.Type}' was specified
- Unsupported content type {content.GetType().Name}. Cannot co
- ImageContent cannot be converted to ResponseContentPart. Onl
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/0b7b6af7e9c28e9f.
Report an issue: GitHub.