{"record":{"id":"45a3ec4825d54802","repo":"PrefectHQ/fastmcp","slug":"imagecontent-is-only-supported-in-user-messages-fo","errorCode":null,"errorMessage":"ImageContent is only supported in user messages for Anthropic","messagePattern":"ImageContent is only supported in user messages for Anthropic","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py","lineNumber":210,"sourceCode":"                ] = []\n\n                for item in content:\n                    if isinstance(item, ToolUseContent):\n                        content_blocks.append(\n                            ToolUseBlockParam(\n                                type=\"tool_use\",\n                                id=item.id,\n                                name=item.name,\n                                input=item.input,\n                            )\n                        )\n                    elif isinstance(item, TextContent):\n                        content_blocks.append(\n                            TextBlockParam(type=\"text\", text=item.text)\n                        )\n                    elif isinstance(item, ImageContent):\n                        if message.role != \"user\":\n                            raise ValueError(\n                                \"ImageContent is only supported in user messages \"\n                                \"for Anthropic\"\n                            )\n                        content_blocks.append(_image_content_to_anthropic_block(item))\n                    elif isinstance(item, AudioContent):\n                        raise ValueError(\n                            \"AudioContent is not supported by the Anthropic API\"\n                        )\n                    elif isinstance(item, ToolResultContent):\n                        # Extract text content from the result\n                        result_content: str | list[TextBlockParam] = \"\"\n                        if item.content:\n                            text_blocks: list[TextBlockParam] = [\n                                TextBlockParam(type=\"text\", text=sub_item.text)\n                                for sub_item in item.content\n                                if isinstance(sub_item, TextContent)\n                            ]\n                            if len(text_blocks) == 1:","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py#L192-L228","documentation":"ValueError from `_convert_to_anthropic_messages` (list-content branch): Anthropic's API only accepts image blocks in user-role messages, so an ImageContent found in an assistant (or other non-user) message is rejected.","triggerScenarios":"A sampling message with role != \"user\" whose content is a list containing an ImageContent item; typically assistant messages carrying image blocks in the conversation history passed to the Anthropic handler.","commonSituations":"Replaying conversation histories where images were attached to assistant turns; multi-turn sampling contexts built by middleware that doesn't enforce role constraints.","solutions":["Move image content into the user message of the exchange","Drop ImageContent items from non-user messages before invoking the handler","Rewrite the assistant turn as text describing the image","Filter/normalize messages before passing the SamplingMessage list"],"exampleFix":"// before\nmessages = [SamplingMessage(role=\"assistant\", content=[ImageContent(...)]), ...]\n\n// after\nmessages = [SamplingMessage(role=\"assistant\", content=[TextContent(type=\"text\", text=\"(image shown to user)\")]), ...]","handlingStrategy":"validation","validationCode":"def strip_nonuser_images(messages):\n    return [\n        m if m.role == \"user\"\n        else SamplingMessage(role=m.role, content=[b for b in as_list(m.content) if not isinstance(b, ImageContent)])\n        for m in messages\n    ]","typeGuard":"def images_only_in_user_messages(messages) -> bool:\n    from mcp.types import ImageContent\n    return all(\n        m.role == \"user\" or not any(isinstance(b, ImageContent) for b in as_list(m.content))\n        for m in messages\n    )","tryCatchPattern":null,"preventionTips":["Never attach ImageContent to assistant messages","Normalize conversation history roles before sampling","Move images to the user turn that references them","Add a message-shape linter/check before provider calls"],"tags":["anthropic","sampling","image","message-role"],"backgroundTag":"unsupported-content-placement","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}