{"record":{"id":"aa23f0d4aef248f8","repo":"microsoft/semantic-kernel","slug":"no-functionresultcontent-found-in-the-message-item","errorCode":null,"errorMessage":"No FunctionResultContent found in the message items","messagePattern":"No FunctionResultContent found in the message items","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/ai/azure_ai_inference/services/utils.py","lineNumber":144,"sourceCode":"\n\ndef _format_tool_message(message: ChatMessageContent) -> ToolMessage:\n    \"\"\"Format a tool message to the expected object for the client.\n\n    Args:\n        message: The tool message.\n\n    Returns:\n        The formatted tool message.\n    \"\"\"\n    if len(message.items) != 1:\n        logger.warning(\n            \"Unsupported number of items in Tool message while formatting chat history for Azure AI\"\n            f\" Inference: {len(message.items)}\"\n        )\n\n    if not isinstance(message.items[0], FunctionResultContent):\n        raise ValueError(\"No FunctionResultContent found in the message items\")\n\n    # The API expects the result to be a string, so we need to convert it to a string\n    return ToolMessage(\n        content=str(message.items[0].result), tool_call_id=message.items[0].id if message.items[0].id else \"None\"\n    )\n\n\nMESSAGE_CONVERTERS: dict[AuthorRole, Callable[[ChatMessageContent], ChatRequestMessage]] = {\n    AuthorRole.SYSTEM: _format_system_message,\n    AuthorRole.USER: _format_user_message,\n    AuthorRole.ASSISTANT: _format_assistant_message,\n    AuthorRole.TOOL: _format_tool_message,\n    AuthorRole.DEVELOPER: _format_developer_message,\n}\n","sourceCodeStart":126,"sourceCodeEnd":159,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/ai/azure_ai_inference/services/utils.py#L126-L159","documentation":"Raised in _format_tool_message when formatting a TOOL-role ChatMessageContent whose first item is not a FunctionResultContent. The Azure AI Inference connector expects each tool message to carry exactly one tool result (it warns if there are more/fewer items, and hard-fails if the first item is not the expected result type), because it must extract .result and .id to build the API's tool message payload.","triggerScenarios":"A TOOL message whose items list is empty or whose first item is a different content type (e.g. a stray TextContent, FunctionCallContent, or ImageContent). Often a result of manually constructing a tool message without wrapping the result in FunctionResultContent.","commonSituations":"Building tool messages by hand instead of through the function-invocation pipeline; mixing content types into a tool message; bugs in middleware that replace items on tool messages.","solutions":["Ensure each TOOL message contains exactly one FunctionResultContent with .result (and ideally .id matching the tool_call_id).","If you have multiple results, split into separate TOOL messages or ensure only FunctionResultContent items are present.","Use SK's function-invocation middleware to produce tool messages rather than constructing them manually."],"exampleFix":"# before\nhistory.add_message(ChatMessageContent(\n    role=AuthorRole.TOOL,\n    items=[TextContent(text=\"42\")],  # wrong item type → error\n))\n\n# after\nfrom semantic_kernel.contents import FunctionResultContent\nhistory.add_message(ChatMessageContent(\n    role=AuthorRole.TOOL,\n    items=[FunctionResultContent(id=call_id, name=\"calc\", result=\"42\")],\n))","handlingStrategy":"validation","validationCode":"from semantic_kernel.contents import FunctionResultContent\n\ndef tool_messages_have_result(history):\n    for m in history:\n        if m.role.name == \"TOOL\":\n            assert m.items and isinstance(m.items[0], FunctionResultContent), \\\n                \"Each TOOL message must start with a FunctionResultContent\"\n\n# call before sending history to the service","typeGuard":"from semantic_kernel.contents import FunctionResultContent\n\ndef is_valid_tool_message(message) -> bool:\n    return (\n        message.role.name == \"TOOL\"\n        and len(message.items) == 1\n        and isinstance(message.items[0], FunctionResultContent)\n    )","tryCatchPattern":"try:\n    await service.get_chat_message_contents(history=history, settings=settings)\nexcept ValueError as e:\n    if \"FunctionResultContent\" in str(e):\n        # rebuild the offending tool message with a FunctionResultContent item\n        ...","preventionTips":["Always wrap tool results in FunctionResultContent.","Use SK's function-invocation pipeline instead of manual tool messages.","Keep exactly one result item per TOOL message."],"tags":["azure-ai-inference","function-calling","chat-history","validation","python"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}