{"record":{"id":"2a1de33c35463644","repo":"PrefectHQ/fastmcp","slug":"unsupported-content-type-type-content","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/anthropic.py","lineNumber":331,"sourceCode":"            # Handle ImageContent\n            if isinstance(content, ImageContent):\n                if message.role != \"user\":\n                    raise ValueError(\n                        \"ImageContent is only supported in user messages for Anthropic\"\n                    )\n                anthropic_messages.append(\n                    MessageParam(\n                        role=\"user\",\n                        content=[_image_content_to_anthropic_block(content)],\n                    )\n                )\n                continue\n\n            # Handle AudioContent - not supported by Anthropic\n            if isinstance(content, AudioContent):\n                raise ValueError(\"AudioContent is not supported by the Anthropic API\")\n\n            raise ValueError(f\"Unsupported content type: {type(content)}\")\n\n        return anthropic_messages\n\n    @staticmethod\n    def _message_to_create_message_result(\n        message: Message,\n    ) -> CreateMessageResult:\n        if len(message.content) == 0:\n            raise ValueError(\"No content in response from Anthropic\")\n\n        # Join all text blocks to avoid dropping content\n        text = \"\".join(\n            block.text for block in message.content if isinstance(block, TextBlock)\n        )\n        if text:\n            return CreateMessageResult(\n                content=TextContent(type=\"text\", text=text),\n                role=\"assistant\",","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py#L313-L349","documentation":"AnthropicSamplingHandler._convert_to_anthropic_messages raises ValueError when an MCP sampling message contains a content type the Anthropic Messages API cannot represent (anything other than TextContent, ImageContent, or AudioContent, which is explicitly rejected earlier). It is a defensive guard so unsupported MCP content never silently reaches the API.","triggerScenarios":"A server sends a sampling request whose message content is an EmbeddedResource (or any non-Text/Image/Audio MCP content block, e.g. resource_link) to a client using AnthropicSamplingHandler.","commonSituations":"Servers returning tool results or resources inline in sampling prompts; MCP servers forwarding AudioContent; new MCP content types added after the handler was written.","solutions":["Inspect the sampling message's content types before choosing the Anthropic handler and strip/downgrade unsupported blocks to text.","Handle AudioContent separately — Anthropic API does not accept audio; convert or drop it upstream.","Use a different sampling handler (e.g. OpenAI or a fallback handler) that supports the content types your server sends.","Catch ValueError in your sampling callback and return a polite refusal message to the server."],"exampleFix":"// before\nclient = Client(transport, sampling_handler=AnthropicSamplingHandler(api_key=...))\n// after\nfrom fastmcp.client.sampling import AnthropicSamplingHandler\nclass SafeHandler(AnthropicSamplingHandler):\n    async def __call__(self, messages, params, context):\n        messages = [m for m in messages if not any(isinstance(c, AudioContent) for c in ([m.content] if not isinstance(m.content, list) else m.content))]\n        return await super().__call__(messages, params, context)","handlingStrategy":"validation","validationCode":"from mcp.types import TextContent, ImageContent\nSUPPORTED = (TextContent, ImageContent)\ndef validate_sampling_messages(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 not isinstance(c, SUPPORTED):\n                raise ValueError(f\"Anthropic handler cannot send {type(c).__name__}\")","typeGuard":"def is_anthropic_supported(c) -> bool:\n    return isinstance(c, (TextContent, ImageContent))","tryCatchPattern":"try:\n    result = await handler(messages, params, context)\nexcept ValueError as e:\n    if \"Unsupported content type\" in str(e):\n        result = CreateMessageResult(content=TextContent(type=\"text\", text=\"Cannot process this content type.\"), role=\"assistant\", model=\"unknown\")\n    else:\n        raise","preventionTips":["Keep sampling prompts text/image-only when using the Anthropic handler","Avoid AudioContent — Anthropic API does not accept it","Wrap sampling callbacks with a content-normalizing layer","Pin and update fastmcp-slim to track new MCP content types"],"tags":["anthropic","sampling","unsupported-content","valueerror"],"backgroundTag":"unsupported-content-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}