BerriAI/litellm · error · NotImplementedError

Bedrock batch embedding currently supports only Amazon…

Error message

Bedrock batch embedding currently supports only Amazon Titan Text Embeddings V2 (model id contains 'titan-embed-text-v2'). Got model={model!r}. Track other embedding models in https://github.com/BerriAI/litellm/issues.

What it means

LiteLLM's Bedrock batch path only implements the InvokeModel schema for Amazon Titan Text Embeddings V2. When the record's model (after litellm.model_alias_map resolution) does not contain 'titan-embed-text-v2', it refuses early instead of silently building a modelInput for the wrong provider, because each embedding model has a different InvokeModel body. The synchronous /v1/embeddings endpoint supports more models, but batch mappings for others are not yet written.

Solutions

  1. Switch the record's model to a Titan v2 id such as 'amazon.titan-embed-text-v2:0' (cross-region prefixes like 'us.amazon.titan-embed-text-v2:0' are detected via the substring fallback)
  2. If you must embed with Cohere/Titan G1/Nova, use the real-time /v1/embeddings path instead of batch
  3. Check litellm.model_alias_map for an override remapping your model to a non-Titan-v2 id
  4. File or upvote a GitHub issue (BerriAI/litellm) for the embedding model you need in batch

Example fix

// before (JSONL line)
{"custom_id": "req_1", "url": "/v1/embeddings", "body": {"model": "cohere.embed-english-v3:0", "input": "hello"}}

// after
{"custom_id": "req_1", "url": "/v1/embeddings", "body": {"model": "amazon.titan-embed-text-v2:0", "input": "hello"}}
Defensive patterns

Strategy: fallback

Validate before calling

TITAN_V2 = "titan-embed-text-v2"

def batch_embedding_supported(model: str) -> bool:
    return TITAN_V2 in model

assert all(batch_embedding_supported(r["body"]["model"]) for r in records if r.get("url") == "/v1/embeddings")

Type guard

def is_titan_v2_embed_model(model: str) -> bool:
    return "titan-embed-text-v2" in model

Try / catch

try:
    file = await client.files.create(file=batch_file, purpose="batch")
except NotImplementedError as e:
    if "Titan Text Embeddings V2" in str(e):
        # fall back to real-time embeddings for this workload
        results = [await client.embeddings.create(model=m, input=x) for m, x in embedding_pairs]

Prevention

When it happens

Trigger: A batch file containing an embedding record whose body.model is e.g. 'amazon.titan-embed-text-v1:0', 'cohere.embed-english-v3:0', or 'amazon.nova-embed-v1', or a model_alias_map entry that resolves to one of those. Also triggered when no model resolves and the target model string lacks the marker.

Common situations: Porting an existing OpenAI/Bedrock embedding batch job to LiteLLM files API; using a company alias that points at Cohere/Titan G1 embeddings; assuming batch parity with the sync /v1/embeddings model list.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/72782dbca0307c72. Report an issue: GitHub.

Appendix: source

Thrown at litellm/llms/bedrock/files/transformation.py:673

        Currently routes Amazon Titan Text Embeddings V2 only; other
        embedding providers (Titan G1, Titan Multimodal, Cohere Embed,
        Nova Multimodal Embeddings) raise NotImplementedError until they
        get a dedicated branch. Splitting them keeps PR scope tight and
        lets each model's request schema be exercised by its own tests.

        AWS docs (Titan v2 InvokeModel body):
        https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-titan-embed-text.html
        """
        from litellm.llms.bedrock.embed.amazon_titan_v2_transformation import (
            AmazonTitanV2Config,
        )

        if not self._is_titan_v2_embed_model(model):
            # Refuse early instead of silently shaping the body for the wrong
            # provider. The synchronous /v1/embeddings path supports more
            # models, but each has a different InvokeModel schema; mapping
            # them here without dedicated tests would risk corrupt batches.
            raise NotImplementedError(
                "Bedrock batch embedding currently supports only Amazon "
                "Titan Text Embeddings V2 (model id contains "
                f"'titan-embed-text-v2'). Got model={model!r}. Track other "
                "embedding models in https://github.com/BerriAI/litellm/issues."
            )

        input_text: Final = self._coerce_embedding_input_to_string(openai_request_body.get("input"), model=model)

        # Map OpenAI-style params (dimensions, encoding_format) onto the
        # Titan v2 schema (dimensions, embeddingTypes) via the embed config
        # so this stays in sync with the synchronous /v1/embeddings path.
        non_default_params: Final = {k: v for k, v in openai_request_body.items() if k not in ("model", "input")}
        titan_config: Final = AmazonTitanV2Config()
        inference_params: Final = titan_config.map_openai_params(
            non_default_params=non_default_params,
            optional_params={},
        )
        return dict(titan_config._transform_request(input=input_text, inference_params=inference_params))

View on GitHub (pinned to 77b7c6c40c)