BoundaryML/baml · error

AWS Bedrock requires s3:// URIs, but got: {}

Error message

AWS Bedrock requires s3:// URIs, but got: {}

What it means

media_to_content_block_json validates that any URL-referenced media sent to AWS Bedrock modular requests uses an s3:// URI, because the Converse API S3Location source only accepts S3 URIs. If the URL scheme is anything else (https://, http://, file://, typoed s3:/), the client bails with this error before making the API call.

Source

Thrown at engine/baml-runtime/src/internal/llm_client/primitive/aws/aws_client.rs:89

fn strip_mime_prefix(mime: &str) -> &str {
    mime.split_once('/').map(|(_, s)| s).unwrap_or(mime)
}

fn media_to_content_block_json(media: &BamlMedia) -> Result<serde_json::Value> {
    let content_block = {
        let mut obj = Map::new();
        if let Some(mime) = media.mime_type.as_deref() {
            obj.insert("format".into(), json!(strip_mime_prefix(mime)));
        }
        let source = match &media.content {
            BamlMediaContent::File(media_file) => todo!(),
            BamlMediaContent::Url(url) => {
                let parsed = Url::parse(&url.url).with_context(|| {
                    format!("Invalid S3 URI for AWS Bedrock video source: {url}")
                })?;

                if parsed.scheme() != "s3" {
                    anyhow::bail!("AWS Bedrock requires s3:// URIs, but got: {}", url.url);
                }

                // unimplemented!("make sure the test works")
                json!({
                    "s3Location": {
                        "uri": url.url,
                    }
                })
            }
            BamlMediaContent::Base64(base64) => json!({
                "bytes": base64.base64,
            }),
        };
        obj.insert("source".into(), source);
        obj
    };
    match media.media_type {
        // _ => anyhow::bail!("AWS Bedrock only supports base64 image inputs in modular requests"),

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Upload the media to S3 and reference it as s3://bucket-name/key (with a valid bucket in the same region the model is invoked in).
  2. Or send the media as a base64 data URL so it goes through the bytes path instead of s3Location.
  3. Verify the URI parses and has scheme 's3' before calling the client (note: a bare bucket name is not valid; the scheme must be s3).

Example fix

// before
media video "https://mybucket.s3.amazonaws.com/clip.mp4"
// after
media video "s3://mybucket/clip.mp4"
Defensive patterns

Strategy: validation

Validate before calling

from urllib.parse import urlparse
url = media['content']['url']
if urlparse(url).scheme != 's3':
    raise ValueError(f"Bedrock video source must be s3:// URI, got {url}")

Type guard

def is_s3_uri(u: str) -> bool:
    return u.lower().startswith('s3://')

Prevention

When it happens

Trigger: Passing a media part with BamlMediaContent::Url whose url does not start with s3:// (e.g. a public https URL or a malformed 's3:/bucket/key') while targeting an aws-bedrock client.

Common situations: Reusing prompt media (https URLs) that worked with OpenAI/Anthropic providers on a Bedrock client; writing S3 URIs without the double slash; referencing presigned CloudFront URLs instead of S3 URIs.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/c5c3a81257d9de00. Report an issue: GitHub.