{"record":{"id":"926e69db05c563e1","repo":"PrefectHQ/fastmcp","slug":"unsupported-content-type-type-content-926e69","errorCode":null,"errorMessage":"Unsupported content type: {type(content)}","messagePattern":"Unsupported content type: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/client/sampling/handlers/openai.py","lineNumber":383,"sourceCode":"                    )\n                )\n                continue\n\n            # Handle AudioContent\n            if isinstance(content, AudioContent):\n                if message.role != \"user\":\n                    raise ValueError(\n                        \"AudioContent is only supported in user messages for OpenAI\"\n                    )\n                openai_messages.append(\n                    ChatCompletionUserMessageParam(\n                        role=\"user\",\n                        content=[_audio_content_to_openai_part(content)],\n                    )\n                )\n                continue\n\n            raise ValueError(f\"Unsupported content type: {type(content)}\")\n\n        return openai_messages\n\n    @staticmethod\n    def _chat_completion_to_create_message_result(\n        chat_completion: ChatCompletion,\n    ) -> CreateMessageResult:\n        if len(chat_completion.choices) == 0:\n            raise ValueError(\"No response for completion\")\n\n        first_choice = chat_completion.choices[0]\n\n        if content := first_choice.message.content:\n            return CreateMessageResult(\n                content=TextContent(type=\"text\", text=content),\n                role=\"assistant\",\n                model=chat_completion.model,\n            )","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/client/sampling/handlers/openai.py#L365-L401","documentation":"The message converter handles ToolUseContent, ToolResultContent, TextContent, ImageContent, and AudioContent. Any other content item type in a SamplingMessage falls through all isinstance checks and raises this ValueError naming the offending type.","triggerScenarios":"A SamplingMessage whose content list contains a content type not in the supported set (e.g. a custom or newly added MCP content class, EmbeddedResource, or a None) is passed to the OpenAI sampling handler.","commonSituations":"MCP SDK version mismatches introducing new content types the handler doesn't know; custom content subclasses from server-side middleware; passing ResourceContents or embedded resources directly instead of converting them to TextContent/ImageContent first.","solutions":["Inspect the message and convert unsupported content to TextContent (e.g. serialize the resource) before sampling.","Check MCP SDK versions on client and server match so both sides agree on content types.","Add a pre-conversion step that strips or flattens unknown content types from SamplingMessage.content lists.","Catch ValueError, log type(content), and degrade gracefully to text-only sampling."],"exampleFix":"// before\nSamplingMessage(role='user', content=[EmbeddedResource(resource=...), TextContent(...)])\n// after\nSamplingMessage(role='user', content=[TextContent(type='text', text=resource_to_text(resource)), TextContent(...)])","handlingStrategy":"type-guard","validationCode":"SUPPORTED = (TextContent, ImageContent, AudioContent, ToolUseContent, ToolResultContent)\ndef assert_supported_content(messages):\n    for m in messages:\n        for c in m.content:\n            if not isinstance(c, SUPPORTED):\n                raise ValueError(f'Content type {type(c).__name__} unsupported by OpenAI handler')","typeGuard":"from mcp.types import Content\nSUPPORTED = (TextContent, ImageContent, AudioContent, ToolUseContent, ToolResultContent)\ndef is_supported_content(c: Content) -> bool:\n    return isinstance(c, SUPPORTED)","tryCatchPattern":"try:\n    result = await openai_handler(messages, params)\nexcept ValueError as e:\n    if str(e).startswith('Unsupported content type:'):\n        messages = flatten_to_text(messages)  # serialize/convert unknown parts\n        result = await openai_handler(messages, params)\n    else:\n        raise","preventionTips":["Convert EmbeddedResource and custom content to TextContent before sampling","Pin matching MCP SDK versions on client and server","Filter unknown content types in a middleware layer","Keep an allowlist of content types for each provider handler"],"tags":["openai","sampling","type-error","content-conversion"],"backgroundTag":"unsupported-content-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}