{"record":{"id":"9778528e5fd21dce","repo":"PrefectHQ/fastmcp","slug":"unsupported-tool-result-content-type-type-item","errorCode":null,"errorMessage":"Unsupported tool result content type: {type(item).__name__}","messagePattern":"Unsupported tool result content type: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py","lineNumber":249,"sourceCode":"        # See: https://ai.google.dev/gemini-api/docs/thought-signatures\n        return Part(\n            function_call=FunctionCall(\n                name=content.name,\n                args=content.input,\n            ),\n            thought_signature=b\"skip_thought_signature_validator\",\n        )\n\n    if isinstance(content, ToolResultContent):\n        # Extract text from tool result content\n        result_parts: list[str] = []\n        if content.content:\n            for item in content.content:\n                if isinstance(item, TextContent):\n                    result_parts.append(item.text)\n                else:\n                    msg = f\"Unsupported tool result content type: {type(item).__name__}\"\n                    raise ValueError(msg)\n        result_text = \"\".join(result_parts)\n\n        # Extract function name from toolUseId\n        # Our IDs are formatted as \"{function_name}_{uuid8}\", so extract the name.\n        # Note: This is a limitation of MCP's ToolResultContent which only carries\n        # toolUseId, while Google's FunctionResponse requires the function name.\n        tool_use_id = content.tool_use_id\n        if \"_\" in tool_use_id:\n            # Split and rejoin all but the last part (the UUID suffix)\n            parts = tool_use_id.rsplit(\"_\", 1)\n            function_name = parts[0]\n        else:\n            # Fallback: use the full ID as the name\n            function_name = tool_use_id\n\n        return Part(\n            function_response=FunctionResponse(\n                name=function_name,","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py#L231-L267","documentation":"_sampling_content_to_google_genai_part raises ValueError when a ToolResultContent block contains an item whose type is not TextContent (e.g. ImageContent or EmbeddedResource). Google GenAI function responses are text-only here, so non-text tool-result items are rejected.","triggerScenarios":"A server returns a tool result whose content list includes images/audio/resources, and the client routes sampling through GoogleGenaiSamplingHandler.","commonSituations":"Tools returning screenshots or files in results; servers attaching resources to tool outputs; rich tool results designed for clients that support multimodal content.","solutions":["Make tools return plain text results when the client uses the Gemini sampling handler.","Strip/downgrade non-text items from tool result content before invoking the handler.","Catch ValueError and serialize the offending item to a text description in your sampling callback.","Use a handler/provider that supports multimodal tool results if rich results are required."],"exampleFix":"// before\ndef my_tool(path: str) -> ImageContent: ...\n// after\ndef my_tool(path: str) -> str:\n    return f\"Image at {path}: <describe or omit>\"","handlingStrategy":"type-guard","validationCode":"from mcp.types import TextContent\ndef validate_tool_results(messages):\n    for m in messages:\n        contents = m.content if isinstance(m.content, list) else [m.content]\n        for c in contents:\n            if hasattr(c, \"content\") and c.content:  # ToolResultContent\n                for item in c.content:\n                    if not isinstance(item, TextContent):\n                        raise ValueError(f\"Tool result item {type(item).__name__} not supported by Gemini handler\")","typeGuard":"def is_text_tool_result(c) -> bool:\n    return not hasattr(c, \"content\") or all(isinstance(i, TextContent) for i in (c.content or []))","tryCatchPattern":"try:\n    result = await handler(messages, params, context)\nexcept ValueError as e:\n    if \"Unsupported tool result content type\" in str(e):\n        result = CreateMessageResult(content=TextContent(type=\"text\", text=\"Tool returned non-text output that cannot be forwarded.\"), role=\"assistant\", model=\"unknown\")\n    else:\n        raise","preventionTips":["Design tools to return plain text when clients sample via Gemini","Serialize images/resources in tool results to text descriptions","Test tool flows end-to-end with the Gemini handler","Document the text-only tool-result constraint for server authors"],"tags":["google-genai","sampling","tool-result","unsupported-content"],"backgroundTag":"unsupported-content-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}