PrefectHQ/fastmcp · error · ValueError
Unsupported content type for OpenAI: {type(item).__name__}
Error message
Unsupported content type for OpenAI: {type(item).__name__} What it means
While converting MCP sampling messages to OpenAI format, tool-result messages may only contain text (and resource content that resolves to text); any other content type inside a tool result raises ValueError naming the Python class. This reflects OpenAI's requirement that tool messages carry plain text content.
Source
Thrown at fastmcp_slim/fastmcp/client/sampling/handlers/openai.py:249
elif isinstance(item, ToolResultContent):
# Collect tool results (added after assistant message)
content_text = ""
if item.content:
result_texts = [
sub_item.text
for sub_item in item.content
if isinstance(sub_item, TextContent)
]
content_text = "\n".join(result_texts)
tool_messages.append(
ChatCompletionToolMessageParam(
role="tool",
tool_call_id=item.tool_use_id,
content=content_text,
)
)
else:
raise ValueError(
f"Unsupported content type for OpenAI: {type(item).__name__}"
)
# Add assistant message with tool calls if present
# OpenAI requires: assistant (with tool_calls) -> tool messages
if tool_calls or content_parts:
if tool_calls:
has_multimodal = len(content_parts) > len(text_parts)
if has_multimodal:
raise ValueError(
"ImageContent/AudioContent is only supported "
"in user messages for OpenAI"
)
text_str = "\n".join(text_parts) or None
openai_messages.append(
ChatCompletionAssistantMessageParam(
role="assistant",
content=text_str,View on GitHub (pinned to 1f02114297)
Solutions
- Convert non-text tool results to text (e.g. describe or caption the image, transcribe audio) before including them.
- Move images/audio into a subsequent user message instead of a tool message.
- Omit unsupported content items from the tool result.
- Use a sampling handler whose provider supports multimodal tool results.
Example fix
// before SamplingMessage(role='tool', tool_use_id=id, content=[ImageContent(...)]) // after SamplingMessage(role='tool', tool_use_id=id, content=[TextContent(type='text', text='Tool returned an image (see next message)')])
Defensive patterns
Strategy: validation
Validate before calling
for m in messages:
if m.role == 'tool':
for c in m.content:
if getattr(c, 'type', None) != 'text':
raise ValueError(f"Tool result contains non-text content: {type(c).__name__}") Type guard
def is_text_only_tool_result(m) -> bool:
return m.role != 'tool' or all(getattr(c, 'type', None) == 'text' for c in m.content) Try / catch
try:
result = await client.sample(...)
except ValueError as e:
if 'Unsupported content type for OpenAI' in str(e):
messages = stringify_tool_results(messages)
result = await client.sample(messages=messages, ...)
else:
raise Prevention
- Serialize tool outputs to text before returning them as tool messages.
- Keep binary/rich tool results out of sampling histories for OpenAI.
- Move media to user messages where supported.
When it happens
Trigger: A sampling message with role='tool' whose content list contains ImageContent, AudioContent, EmbeddedResource with non-text data, etc., passed through _convert_to_openai_messages during Client.sample().
Common situations: Tool results that return screenshots or audio clips fed back as tool messages; embedding binary resources in tool output; MCP servers returning rich tool results that OpenAI's tool-message schema can't represent.
Related errors
- ImageContent/AudioContent is only supported in user messages
- Unsupported content type: {type(content)}
- Invalid JSON in tool arguments for '{func.name}': {func.argu
- No content in response from completion (finish_reason={finis
- Unsupported image MIME type for OpenAI: {content.mime_type!r
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/e59f642d3603eac0.
Report an issue: GitHub.