BerriAI/litellm · error · ValueError

output_s3_uri cannot be empty for async invoke requests

Error message

output_s3_uri cannot be empty for async invoke requests

What it means

Bedrock's async-invoke API requires an outputDataConfig with an S3 location where the (potentially large) result is written. TwelveLabsMarengoEmbeddingConfig._transform_async_invoke_request validates output_s3_uri before wrapping the request and rejects empty/whitespace values.

Source

Thrown at litellm/llms/bedrock/embed/twelvelabs_marengo_transformation.py:181

        Args:
            model_input: The transformed TwelveLabs Marengo embedding request
            model_id: The model identifier (without async_invoke prefix)
            output_s3_uri: Optional S3 URI for output data config

        Returns:
            TwelveLabsAsyncInvokeRequest: The wrapped async invoke request
        """
        import urllib.parse

        # Clean the model ID
        unquoted_model_id = urllib.parse.unquote(model_id)
        if unquoted_model_id.startswith("async_invoke/"):
            unquoted_model_id = unquoted_model_id.replace("async_invoke/", "")

        # Validate that the S3 URI is not empty
        if not output_s3_uri or output_s3_uri.strip() == "":
            raise ValueError("output_s3_uri cannot be empty for async invoke requests")

        return TwelveLabsAsyncInvokeRequest(
            modelId=unquoted_model_id,
            modelInput=model_input,
            outputDataConfig=TwelveLabsOutputDataConfig(
                s3OutputDataConfig=TwelveLabsS3OutputDataConfig(s3Uri=output_s3_uri)
            ),
        )

    def _transform_response(self, response_list: list[dict], model: str) -> EmbeddingResponse:
        """
        Transform TwelveLabs response to OpenAI format.
        Handles the actual TwelveLabs response format: {"data": [{"embedding": [...]}]}
        """
        embeddings: Final[list[Embedding]] = []
        total_tokens = 0

        for response in response_list:

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Pass a valid S3 URI as output_s3_uri, e.g. 's3://my-bucket/embeddings-output/'.
  2. Ensure the Bedrock principal has s3:PutObject access to that bucket/prefix.
  3. Set the env var / config feeding output_s3_uri in every environment that uses async invoke.

Example fix

# before
litellm.embedding(model="bedrock/async_invoke/twelvelabs.marengo-embed-2.7", input=[url], input_type="video")

# after
litellm.embedding(
    model="bedrock/async_invoke/twelvelabs.marengo-embed-2.7",
    input=[url],
    input_type="video",
    output_s3_uri="s3://my-bucket/embeddings-out/",
)
Defensive patterns

Strategy: validation

Validate before calling

def validate_async_invoke(output_s3_uri: str | None):
    if not output_s3_uri or not output_s3_uri.strip():
        raise ValueError("output_s3_uri required")
    if not output_s3_uri.startswith("s3://"):
        raise ValueError("output_s3_uri must be an s3:// URI")

Type guard

def is_valid_s3_uri(uri: str | None) -> bool:
    import re
    return bool(uri) and bool(re.match(r"^s3://[^/\s]+/.+", uri.strip()))

Prevention

When it happens

Trigger: Using 'bedrock/async_invoke/twelvelabs.marengo-embed-2.7' without passing output_s3_uri, or passing a whitespace-only string, when constructing the async invoke request.

Common situations: Assuming the async result comes back in the HTTP response instead of via S3; wiring output_s3_uri from an env var that is unset in some environments.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/f835444dcf3bf153. Report an issue: GitHub.