{"record":{"id":"d037ecd4ea4c8c07","repo":"BoundaryML/baml","slug":"baml-internal-error-openai-responses-image-file-should-have","errorCode":null,"errorMessage":"BAML internal error (openai-responses): image file should have been resolved, not processed directly.","messagePattern":"BAML internal error \\(openai-responses\\): image file should have been resolved, 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":149,"sourceCode":"            // For assistant role, we only support text outputs in Responses API.\n            if role == \"assistant\" {\n                anyhow::bail!(\n                    \"BAML internal error (openai-responses): assistant messages must be text; media not supported for assistant in Responses API\"\n                );\n            }\n            match media.media_type {\n                baml_types::BamlMediaType::Image => {\n                    let image_url = match &media.content {\n                        baml_types::BamlMediaContent::Url(url_content) => url_content.url.clone(),\n                        baml_types::BamlMediaContent::Base64(b64_media) => {\n                            format!(\n                                \"data:{};base64,{}\",\n                                media.mime_type_as_ok()?,\n                                b64_media.base64\n                            )\n                        }\n                        baml_types::BamlMediaContent::File(_) => {\n                            anyhow::bail!(\n                                \"BAML internal error (openai-responses): image file should have been resolved, not processed directly.\"\n                            );\n                        }\n                    };\n                    Ok(json!({\n                        \"type\": \"input_image\",\n                        \"detail\": \"auto\",\n                        \"image_url\": image_url\n                    }))\n                }\n                baml_types::BamlMediaType::Audio => match &media.content {\n                    baml_types::BamlMediaContent::Base64(b64_media) => {\n                        let mime_type = media.mime_type_as_ok()?;\n                        let format = mime_type.strip_prefix(\"audio/\").unwrap_or(&mime_type);\n                        Ok(json!({\n                            \"type\": \"input_audio\",\n                            \"input_audio\": {\n                                \"data\": b64_media.base64,","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-runtime/src/internal/llm_client/primitive/openai/openai_client.rs#L131-L167","documentation":"While building an `input_image` content part for the OpenAI Responses API, BAML encountered an image whose content is still `BamlMediaContent::File` — a local file reference. By contract, file-based media must be resolved (loaded into URL or base64 form) earlier in the media pipeline, so hitting this arm means an unresolved local file image reached the provider-body builder. It is an internal invariant check, indicating the media-resolution step was skipped or failed silently.","triggerScenarios":"Passing an image via `image(...)` with a local file path to a function whose client uses the OpenAI Responses API, in a context where BAML's file-resolution stage did not run (openai_client.rs:149 bails on `BamlMediaContent::File(_)` inside the Image match).","commonSituations":"Referencing a local image file path in a prompt sent to a Responses-API client; a custom/integration path (e.g. programmatic API building chat parts directly) that bypasses BAML's file loading; environment differences where a file that normally resolves at runtime wasn't loaded.","solutions":["Inline the image as base64 (b64) or supply a remote URL instead of a local file reference, both of which the Responses API path supports.","Ensure media goes through BAML's normal resolution (let BAML load files at runtime) rather than constructing ChatMessagePart::File manually.","Verify the image path resolves in your runtime environment; a failed resolution can leave the File variant in place.","If you need direct local-file support for Responses API images, file an issue; currently only Url and Base64 variants are handled."],"exampleFix":"// before: local file reference in a Responses API client\nimage { file \"./cat.png\" }\n\n// after: base64-inline or URL the image\nimage { b64 \"iVBORw0KGgo...\" }\n// or\nimage { url \"https://example.com/cat.png\" }","handlingStrategy":"validation","validationCode":"// before calling the function, ensure images are url or b64, not local files\nassert!(matches!(img.content, BamlMediaContent::Url(_) | BamlMediaContent::Base64(_)),\n        \"image must be url or base64 for Responses API\");","typeGuard":"fn image_is_resolved(media: &BamlMedia) -> bool {\n    matches!(media.content, BamlMediaContent::Url(_) | BamlMediaContent::Base64(_))\n}","tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"should have been resolved\") => {\n        // re-load the media as base64 and rebuild the request\n    }\n    r => r?,\n}","preventionTips":["Always pass images via url or b64 when using a Responses-API client.","Let BAML's runtime load file media; avoid constructing File content parts manually.","Verify file paths resolve in the deployment environment (container vs local)."],"tags":["openai","responses-api","image","file-resolution","rust"],"backgroundTag":"internal-invariant-violation","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"}