microsoft/semantic-kernel · error · ServiceInvalidRequestError

Only text and image content are supported in a user message.

Error message

Only text and image content are supported in a user message.

What it means

Raised while formatting a user-role ChatMessageContent for Bedrock when an item in message.items is neither TextContent nor ImageContent. The Bedrock user-message converter only supports those two content types; everything else (function calls, function results, annotations, file references) is rejected before the request is sent.

Source

Thrown at python/semantic_kernel/connectors/ai/bedrock/services/model_provider/utils.py:62

    """
    return {"text": message.content}


def _format_user_message(message: ChatMessageContent) -> dict[str, Any]:
    """Format a user message to the expected object for the client.

    Note that Guardrails and Documents are currently not supported.

    Args:
        message: The user message.

    Returns:
        The formatted user message.
    """
    contents: list[Any] = []
    for item in message.items:
        if not isinstance(item, (ImageContent, TextContent)):
            raise ServiceInvalidRequestError("Only text and image content are supported in a user message.")

        if isinstance(item, ImageContent):
            contents.append({
                "image": {
                    "format": item.mime_type.removeprefix("image/"),
                    "source": {
                        "bytes": item.data,
                    },
                }
            })
        else:
            contents.append({"text": item.text})

    return {
        "role": "user",
        "content": contents,
    }

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Assign tool outputs to AuthorRole.TOOL messages, not AuthorRole.USER, so they flow through _format_tool_message.
  2. Strip or convert unsupported items (e.g. FunctionResultContent) from user messages before adding them to ChatHistory.
  3. When replaying history, use the MESSAGE_CONVERTERS mapping so each role is formatted by its dedicated converter.

Example fix

// before
history.add_message(ChatMessageContent(role=AuthorRole.USER, items=[FunctionResultContent(...)]))
// after
history.add_message(ChatMessageContent(role=AuthorRole.TOOL, items=[FunctionResultContent(...)]))
Defensive patterns

Strategy: validation

Validate before calling

from semantic_kernel.contents.chat_message_content import ChatMessageContent
from semantic_kernel.contents.image_content import ImageContent
from semantic_kernel.contents.text_content import TextContent

def user_message_is_bedrock_safe(message: ChatMessageContent) -> bool:
    return all(isinstance(i, (TextContent, ImageContent)) for i in message.items)

Type guard

from semantic_kernel.contents.image_content import ImageContent
from semantic_kernel.contents.text_content import TextContent

def is_bedrock_user_item(item: object) -> bool:
    return isinstance(item, (TextContent, ImageContent))

Try / catch

from semantic_kernel.exceptions.service_exceptions import ServiceInvalidRequestError

try:
    await service.get_chat_message_contents(history, settings)
except ServiceInvalidRequestError as e:
    if "Only text and image content are supported in a user message" in str(e):
        history.messages = [sanitize_for_bedrock(m) for m in history.messages]
    raise

Prevention

When it happens

Trigger: A ChatHistory containing a user message whose items include FunctionCallContent, FunctionResultContent, or any non-text/non-image content type, being sent to a Bedrock chat completion service via _format_user_message.

Common situations: Manually constructing a user message with a tool result instead of a tool-role message; replaying a mixed-content assistant/tool history into a user role; loading a chat history from storage that tagged tool results as user role.

Related errors


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