BoundaryML/baml · error
OpenAI transcriptions require chat messages with exactly…
Error message
OpenAI transcriptions require chat messages with exactly one audio media part
What it means
BAML's OpenAI transcription request builder only accepts a chat-style prompt (a list of RenderedChatMessage) containing the audio media; a bare string prompt (Either::Left) has no place to attach audio, so build_transcription_parts rejects it immediately. The error message is slightly misleading — the real requirement is a chat message list, not 'exactly one' at this stage.
Solutions
- Rewrite the BAML function to produce chat messages (e.g. use a message-based prompt with an audio media part) instead of a bare string prompt.
- Ensure the audio file is passed as a media part in one of the chat messages.
- If you only need text-to-text, do not route the function through a transcription client.
Example fix
// before
function Transcribe(audio: Audio) -> string {
client openai/transcribe
prompt #"transcribe"# // plain string prompt
}
// after
function Transcribe(audio: Audio) -> string {
client openai/transcribe
prompt #"
{{ ctx.output_format }}
{{ _.role('user') }}
{{ audio }}
"#
} Defensive patterns
Strategy: validation
Validate before calling
// Ensure the function prompt renders as chat messages containing an audio part
function assertChatAudioPrompt(fn) {
const rendered = baml.renderPrompt(fn);
if (typeof rendered === "string") {
throw new Error("Transcription functions must use a chat-message prompt, not a plain string");
}
} Type guard
const isChatMessages = (p) => Array.isArray(p) && p.some(m => m.parts?.some(pt => pt.type === "audio"));
Prevention
- Always write transcription function prompts as message-based templates with {{ audio }}.
- Keep transcription functions separate from plain string-prompt functions.
- Test each transcription function with a sample audio input before deploying.
When it happens
Trigger: Calling a BAML function whose client is configured for OpenAI transcriptions while the prompt is a plain string (no chat message structure), i.e. the function renders to a raw string instead of chat messages.
Common situations: Writing a BAML function with a plain `string` prompt and pointing it at a transcription-style client; passing a template that renders to text rather than a message[]; older clients/tests that predate the chat-message transcription format.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- OpenAI transcription audio must be resolved to base64…
- OpenAI transcriptions require exactly one audio media part…
- OpenAI transcription prompt is ambiguous: both…
- OpenAI transcriptions do not support reserved request field
- OpenAI transcriptions only support audio media parts
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/9929953d6467aae7.
Report an issue: GitHub.
Appendix: source
Thrown at engine/baml-runtime/src/internal/llm_client/primitive/openai/types.rs:62
#[serde(rename = "transcript.text.done")]
Done {
text: String,
usage: Option<TranscriptionUsage>,
},
#[serde(rename = "transcript.text.segment")]
Segment,
#[serde(other)]
Unknown,
}
pub fn build_transcription_parts(
properties: &BamlMap<String, Value>,
prompt: either::Either<&String, &[RenderedChatMessage]>,
) -> Result<TranscriptionParts> {
let messages = match prompt {
either::Either::Right(messages) => messages,
either::Either::Left(_) => {
bail!("OpenAI transcriptions require chat messages with exactly one audio media part")
}
};
reject_reserved_request_fields(properties)?;
let mut audio_parts = Vec::new();
let mut text_parts = Vec::new();
for message in messages {
for part in &message.parts {
collect_transcription_prompt_parts(part, &mut audio_parts, &mut text_parts)?;
}
}
if audio_parts.len() != 1 {
bail!(
"OpenAI transcriptions require exactly one audio media part, got {}",
audio_parts.len()
);View on GitHub (pinned to bd85ce9dee)