{"record":{"id":"8c59c2dd437a5187","repo":"BoundaryML/baml","slug":"baml-internal-error-openai-audio-file-should-have-been","errorCode":null,"errorMessage":"BAML internal error (openai): audio file should have been resolved to base64, not processed directly.","messagePattern":"BAML internal error \\(openai\\): audio file should have been resolved to base64, not processed directly\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"engine/baml-runtime/src/internal/llm_client/primitive/openai/openai_client.rs","lineNumber":852,"sourceCode":"                        let extension = match media.mime_type.as_deref() {\n                            Some(mime) => mime,\n                            None => match extension {\n                                Some(ext) => ext,\n                                None => anyhow::bail!(\"BAML internal error (openai): audio url has no extension and no mime type\"),\n                            },\n                        };\n\n                        let format_str = match extension {\n                            \"mpeg\" => \"mp3\",\n                            other => other,\n                        };\n                        content.insert(\n                            payload_key.into(),\n                            json!({ \"data\": url_content.url, \"format\": format_str }),\n                        );\n                    }\n                    BamlMediaContent::File(_) => {\n                        anyhow::bail!(\n                            \"BAML internal error (openai): audio file should have been resolved to base64, not processed directly.\"\n                        );\n                    }\n                }\n            }\n            BamlMediaType::Pdf => {\n                let type_value = \"file\";\n                let payload_key = \"file\";\n                content.insert(\"type\".into(), json!(type_value));\n\n                match &media.content {\n                    BamlMediaContent::Url(url_content) => {\n                        // For URLs, we need to resolve them to base64 first\n                        content.insert(\n                            payload_key.into(),\n                            json!({\n                                \"type\": \"input_file\",\n                                \"file_url\": url_content.url,","sourceCodeStart":834,"sourceCodeEnd":870,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-runtime/src/internal/llm_client/primitive/openai/openai_client.rs#L834-L870","documentation":"Audio media in the OpenAI client must be resolved to base64 before provider conversion; a BamlMediaContent::File variant reaching to_media_message indicates the resolution stage was skipped. The client bails because it cannot inline a file reference into the input_audio payload.","triggerScenarios":"Audio media whose content is BamlMediaContent::File when building the OpenAI chat completions body (file never converted to Base64).","commonSituations":"Constructing BamlAudio from a local file path via the SDK without calling base64 conversion, or a runtime bug where file-backed audio bypassed media resolution.","solutions":["Resolve the audio file to base64 before calling the client (force_to_base64 / to_base64)","Pass audio as base64 data or a URL with a usable extension instead of a file reference","Report as a BAML bug if the standard runtime produced an unresolved file"],"exampleFix":"// before\nlet audio = BamlAudio::from_file(\"speech.mp3\");\n// after\nlet audio = BamlAudio::from_file(\"speech.mp3\").to_base64()?;","handlingStrategy":"validation","validationCode":"// resolve file-backed audio before the client call\nif (audio.content.kind === \"file\") {\n  audio = await audio.to_base64();\n}","typeGuard":"fn audio_is_resolved(m: &BamlMedia) -> bool {\n    !matches!(m.content, BamlMediaContent::File(_))\n}","tryCatchPattern":null,"preventionTips":["Convert audio files to base64 before constructing media for SDK calls","Rely on BAML's automatic media resolution rather than manual media objects","Add a preflight assertion that no File content remains before provider conversion"],"tags":["openai","audio","media-resolution","internal-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}