microsoft/semantic-kernel · error · ArgumentOutOfRangeException
Invalid role: {role}
Error message
Invalid role: {role} What it means
BedrockModelUtilities.MapAuthorRoleToConversationRole converts an SK AuthorRole to a Bedrock ConversationRole, but only handles User and Assistant. System is intentionally excluded (it is extracted separately by GetSystemMessages), and any other role falls through to ArgumentOutOfRangeException. This is reached when building the Bedrock message list from ChatHistory.
Source
Thrown at dotnet/src/Connectors/Connectors.Amazon/Bedrock/Core/BedrockModelUtilities.cs:35
/// <summary>
/// Maps the AuthorRole to the corresponding ConversationRole because AuthorRole is static and { readonly get; }. Only called if AuthorRole is User or Assistant (System set outside/beforehand).
/// </summary>
/// <param name="role">The AuthorRole to be converted to ConversationRole</param>
/// <returns>The corresponding ConversationRole</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown if invalid role.</exception>
internal static ConversationRole MapAuthorRoleToConversationRole(AuthorRole role)
{
if (role == AuthorRole.User)
{
return ConversationRole.User;
}
if (role == AuthorRole.Assistant)
{
return ConversationRole.Assistant;
}
throw new ArgumentOutOfRangeException($"Invalid role: {role}");
}
/// <summary>
/// Gets the system messages from the ChatHistory and adds them to the ConverseRequest System parameter.
/// </summary>
/// <param name="chatHistory">The ChatHistory object to be parsed.</param>
/// <returns>The list of SystemContentBlock for the converse request.</returns>
internal static List<SystemContentBlock> GetSystemMessages(ChatHistory chatHistory)
{
return chatHistory
.Where(m => m.Role == AuthorRole.System)
.Select(m => new SystemContentBlock { Text = m.Content })
.ToList();
}
/// <summary>
/// Creates the list of user and assistant messages for the Converse Request from the Chat History.
/// </summary>View on GitHub (pinned to c028a0c7dc)
Solutions
- Ensure every ChatHistory message passed to the Bedrock connector uses AuthorRole.User, AuthorRole.Assistant, or AuthorRole.System only.
- Filter or remap custom roles (tool/function) to Assistant before invoking the Bedrock chat completion service.
- Upgrade Connectors.Amazon if a newer version natively supports the role you need.
Example fix
// before - custom role reaches the Bedrock builder
chatHistory.AddMessage(new AuthorRole("tool"), "{\"result\": 42}");
var result = await chatCompletion.GetChatMessageContentAsync(chatHistory);
// -> ArgumentOutOfRangeException: Invalid role: tool
// after - remap tool results to Assistant before the Bedrock call
for (int i = 0; i < chatHistory.Count; i++)
{
if (chatHistory[i].Role != AuthorRole.User
&& chatHistory[i].Role != AuthorRole.Assistant
&& chatHistory[i].Role != AuthorRole.System)
{
chatHistory[i] = new ChatMessageContent(AuthorRole.Assistant, chatHistory[i].Content);
}
} Defensive patterns
Strategy: validation
Validate before calling
// Before invoking the Bedrock chat completion service, ensure every ChatHistory
// message uses one of the supported AuthorRoles.
static bool IsBedrockSupportedRole(AuthorRole? role)
=> role == AuthorRole.User || role == AuthorRole.Assistant || role == AuthorRole.System;
foreach (var m in chatHistory)
{
if (!IsBedrockSupportedRole(m.Role))
throw new InvalidOperationException($"ChatHistory contains unsupported role '{m.Role}' for Bedrock.");
} Type guard
static bool IsBedrockSupportedRole(AuthorRole? role)
=> role == AuthorRole.User || role == AuthorRole.Assistant || role == AuthorRole.System; Try / catch
try
{
var result = await bedrockChatCompletion.GetChatMessageContentAsync(chatHistory, settings, ct);
}
catch (ArgumentOutOfRangeException ex) when (ex.Message.Contains("Invalid role"))
{
// A non User/Assistant/System role reached the builder. Sanitize ChatHistory and retry.
logger.LogWarning(ex, "ChatHistory contained an unsupported role for Bedrock.");
} Prevention
- Only add User, Assistant, and System messages to ChatHistory used with Bedrock.
- Remap tool/function result messages to Assistant before sending to Bedrock.
- Validate ChatHistory roles in a helper before every Bedrock call.
When it happens
Trigger: A ChatHistory contains a message whose Role is neither User, Assistant, nor System (for example a custom AuthorRole like "tool", "function", or any non-standard string) and that message is not filtered out before BuildMessageList calls MapAuthorRoleToConversationRole. Note BuildMessageList only filters m.Role != AuthorRole.System, so custom roles survive into the mapping.
Common situations: Adding tool/function-call messages or custom roles to ChatHistory used with the Bedrock chat completion connector. Mixing ChatHistory built for function-calling (which may set non-standard roles) into a Bedrock request. Library version that does not support tool roles yet.
Related errors
- Invalid role: {role}
- Last message in chat history was null or whitespace.
- Unsupported AI21 model: {modelId}
- Unsupported Amazon model: {modelId}
- Unsupported Anthropic model: {modelId}
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/945dd24ef952b7e2.
Report an issue: GitHub.