PrefectHQ/fastmcp · error · ValueError

AudioContent is only supported in user messages for OpenAI

Error message

AudioContent is only supported in user messages for OpenAI

What it means

Analogous to the image case: OpenAI chat messages only support audio input parts in user messages, so the handler raises ValueError when AudioContent appears in a sampling message with a non-'user' role during conversion.

Source

Thrown at fastmcp_slim/fastmcp/client/sampling/handlers/openai.py:372

            # Handle ImageContent
            if isinstance(content, ImageContent):
                if message.role != "user":
                    raise ValueError(
                        "ImageContent is only supported in user messages for OpenAI"
                    )
                openai_messages.append(
                    ChatCompletionUserMessageParam(
                        role="user",
                        content=[_image_content_to_openai_part(content)],
                    )
                )
                continue

            # Handle AudioContent
            if isinstance(content, AudioContent):
                if message.role != "user":
                    raise ValueError(
                        "AudioContent is only supported in user messages for OpenAI"
                    )
                openai_messages.append(
                    ChatCompletionUserMessageParam(
                        role="user",
                        content=[_audio_content_to_openai_part(content)],
                    )
                )
                continue

            raise ValueError(f"Unsupported content type: {type(content)}")

        return openai_messages

    @staticmethod
    def _chat_completion_to_create_message_result(
        chat_completion: ChatCompletion,
    ) -> CreateMessageResult:

View on GitHub (pinned to 1f02114297)

Solutions

  1. Move AudioContent into a SamplingMessage with role='user'.
  2. Replace assistant-role audio with a TextContent transcript before calling the handler.
  3. Use a provider/handler that supports audio in assistant messages if that is a hard requirement.
  4. Catch the ValueError and re-encode the message list with audio only in user turns.

Example fix

// before
SamplingMessage(role='assistant', content=[AudioContent(data=..., mimeType='audio/wav')])
// after
SamplingMessage(role='user', content=[AudioContent(data=..., mimeType='audio/wav')])
Defensive patterns

Strategy: validation

Validate before calling

def validate_openai_sampling_messages(messages):
    for m in messages:
        if m.role != 'user' and any(isinstance(c, AudioContent) for c in m.content):
            raise ValueError('AudioContent found in non-user message; move it to a user message')
    return messages

Type guard

def is_user_audio_message(m) -> bool:
    return m.role == 'user' and any(isinstance(c, AudioContent) for c in getattr(m, 'content', []))

Try / catch

try:
    result = await openai_handler(messages, params)
except ValueError as e:
    if 'AudioContent is only supported in user messages' in str(e):
        messages = [m for m in messages if not (m.role != 'user' and any(isinstance(c, AudioContent) for c in m.content))]
        result = await openai_handler(messages, params)
    else:
        raise

Prevention

When it happens

Trigger: Passing a SamplingMessage with role='assistant' (or other non-'user' role) containing AudioContent through the OpenAI sampling handler's _convert_to_openai_messages.

Common situations: Voice-agent pipelines that place transcribed or raw audio in assistant turns; replayed conversation logs where roles were re-mapped incorrectly; server code that attaches generated audio to assistant messages.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/1747c3c6e959d072. Report an issue: GitHub.