{"record":{"id":"42238f1b472c1397","repo":"BoundaryML/baml","slug":"openai-transcription-prompt-is-ambiguous-both-properties","errorCode":null,"errorMessage":"OpenAI transcription prompt is ambiguous: both properties.prompt and rendered text were provided","messagePattern":"OpenAI transcription prompt is ambiguous: both properties\\.prompt and rendered text were provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-runtime/src/internal/llm_client/primitive/openai/types.rs","lineNumber":102,"sourceCode":"        .pop()\n        .expect(\"audio_parts length was already validated\");\n    let mime = audio.mime_type_as_ok()?;\n    let file_bytes = match &audio.content {\n        BamlMediaContent::Base64(media_b64) => BASE64_STANDARD\n            .decode(&media_b64.base64)\n            .context(\"Failed to decode transcription audio as base64\")?,\n        BamlMediaContent::Url(_) | BamlMediaContent::File(_) => {\n            bail!(\"OpenAI transcription audio must be resolved to base64 before request building\")\n        }\n    };\n\n    let mut fields = BamlMap::new();\n    let model = required_string_field(properties, \"model\")?;\n    fields.insert(\"model\".to_string(), model.clone());\n\n    let property_prompt = optional_string_field(properties, \"prompt\")?;\n    if property_prompt.is_some() && !text_parts.is_empty() {\n        bail!(\"OpenAI transcription prompt is ambiguous: both properties.prompt and rendered text were provided\");\n    }\n    let rendered_prompt = (!text_parts.is_empty()).then(|| text_parts.join(\"\\n\"));\n    if let Some(prompt) = property_prompt.or(rendered_prompt) {\n        fields.insert(\"prompt\".to_string(), prompt);\n    }\n\n    if let Some(language) = optional_string_field(properties, \"language\")? {\n        fields.insert(\"language\".to_string(), language);\n    }\n    if let Some(response_format) = optional_response_format(properties, &model)? {\n        fields.insert(\"response_format\".to_string(), response_format);\n    }\n    if let Some(temperature) = optional_temperature(properties)? {\n        fields.insert(\"temperature\".to_string(), temperature);\n    }\n\n    Ok(TranscriptionParts {\n        file_bytes,","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-runtime/src/internal/llm_client/primitive/openai/types.rs#L84-L120","documentation":"The transcription `prompt` field can come from two sources: an explicit `prompt` client property or rendered text from the chat messages. If both are present the intended prompt is ambiguous, so build_transcription_parts refuses to silently pick one and bails.","triggerScenarios":"A transcription client options block that sets `prompt \"...\"` while the BAML function prompt also renders non-empty text parts alongside the audio media part.","commonSituations":"Adding instructions/hints in the BAML prompt text while also having set the OpenAI-style `prompt` option in the client config; copying a client config that already had a prompt property and then editing the template to add text.","solutions":["Remove the `prompt` property from the client options and keep the prompt text in the BAML template.","Or remove the rendered text from the template, keeping only the audio part, and rely on the client's `prompt` property.","Merge the hint text into whichever source you keep."],"exampleFix":"// before\nclient<T> { provider openai options { model \"whisper-1\" prompt \"glossary terms\" } }\nprompt #\"User audio: {{ audio }} Please transcribe carefully.\"#\n// after\nclient<T> { provider openai options { model \"whisper-1\" } }\nprompt #\"{{ _.role('user') }} {{ audio }}\"#","handlingStrategy":"validation","validationCode":"// Check config + rendered prompt for a conflicting prompt source\nfunction assertSinglePromptSource(clientOptions, renderedMessages) {\n  const hasPropPrompt = typeof clientOptions.prompt === \"string\";\n  const hasText = renderedMessages.some(m => m.parts.some(p => p.type === \"text\" && p.text.trim() !== \"\"));\n  if (hasPropPrompt && hasText) throw new Error(\"Remove either the client 'prompt' option or the rendered prompt text\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Decide on one prompt source (client option OR template text) per transcription function.","Keep transcription prompt templates media-only (just the audio part).","Review client options when copying blocks between clients; strip chat-only fields."],"tags":["openai","transcription","config","baml"],"backgroundTag":"conflicting-config-options","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}